/*
 * JavaScript Tetris - 2008/03/05
 *   
 * Copyright (c) 2008 Threeformed Media (http://www.threeformed.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 */

var grid;var preview;var activePiece;var score;var level;var timeout;var linecount;var running=false;var instance;var next=new Object();var ctype;var cstate;var ios = new Object();var wloaded = false;

$(function(){
	//cache images
	var images = ['background', 'red', 'green', 'yellow', 'purple', 'grey', 'orange', 'blue'];
	for(var i=0; i < 8; i++){
		var t = new Image();
		t.src = 'images/'+images[i]+'.gif';
		ios[images[i]] = t;
	}
	
	//fill the grids 
	for(var i=0;i<200;i++){
		$('#grid').append('<li class="block" id="'+i+'"></li>')
	}
	for(var i=0;i<30;i++){
		$('#previewGrid').append('<li class="block" id="p_'+i+'"></li>')
	}
	
	//initialize tetris
	$(window).load(function(){
		init();
		document.onkeydown = keyListener;
		wloaded = true;
	});
	
});

//initialize game vars
function init(){
	$('#gameOver').hide();
	
	score = 0; 
	level = 1;
	linecount = 0;
	timeout = 500;
	
	setGrid(); //initialize main playing grid
	setPreview(); //initialize preview grid
	setPiece();
	getNext();
	setPiece();
	renderGrid(); //render initial grid state
}

//game loop
function loopGame(){
	if(activePiece != 'game over'){
		//every loop begins by dropping the block one level
		shiftDown();
		if(typeof activePiece == 'boolean'){
			//the piece cannot go down any further so get the next piece and loop
			getNext();
			setPiece();
			instance = setTimeout(loopGame, timeout);
		}else{
			instance = setTimeout(loopGame, timeout);
		}
	}	
}

function block(x, y){
	//block represents a single grid square
	//x and y represent the block's position on the grid where the top left block is at coord(0, 0)
	this.x = x; 
	this.y = y;
	this.bcolor = 'background'; //the current image on the block
	this.active = false; 
	this.available = true; //whether the block is available or not 
	block.prototype.render = function(){ 
		$('#'+getB(this.x, this.y)).css({background: 'url('+ios[this.bcolor].src+')'});
	}
	block.prototype.prev = function(){ 
		$('#p_'+getP(this.x, this.y)).css({background: 'url('+ios[this.bcolor].src+')'});
	}
}

//shifts the active piece one block to the left
function shiftLeft(){
	var good = true;
	for(i in activePiece){ 
		if(grid[activePiece[i]].x > 0 && grid[activePiece[i] - 1].available){
			continue
		}else{
			good = false;
			break;
		}
	}
	if(good){ 
		var newPiece = [activePiece[0]-1, activePiece[1]-1, activePiece[2]-1, activePiece[3]-1];
		for(j in activePiece){
			set(grid[activePiece[j] - 1], grid[activePiece[j]].bcolor, true, true);
			grid[activePiece[j] - 1].render();
		}
		for(k in activePiece){
			if(in_array(activePiece[k] + 1, activePiece)){
				set(grid[activePiece[k]], grid[activePiece[k]].bcolor, true, true);
			}else{
				set(grid[activePiece[k]], 'background', false, true);
			}
			grid[activePiece[k]].render();
		}
		activePiece = newPiece;
	}
}

//shifts the active piece one block to the right
function shiftRight(){
	var good = true;
	for(i in activePiece){
		if(grid[activePiece[i]].x < 9 && grid[activePiece[i] + 1].available){
			continue
		}else{
			good = false;
			break;
		}
	}
	if(good){
		var newPiece = [activePiece[0]+1, activePiece[1]+1, activePiece[2]+1, activePiece[3]+1];
		for(j in activePiece){
			set(grid[activePiece[j] + 1], grid[activePiece[j]].bcolor, true, true);
			grid[activePiece[j] + 1].render();
		}
		for(k in activePiece){
			if(in_array(activePiece[k] - 1, activePiece)){
				set(grid[activePiece[k]], grid[activePiece[k]].bcolor, true, true);
			}else{
				set(grid[activePiece[k]], 'background', false, true);
			}
			grid[activePiece[k]].render();
		}
		activePiece = newPiece;
	}
}

//shifts the active piece one block down
function shiftDown(){
	var good = true;
	for(i in activePiece){
		if(grid[activePiece[i]].y < 19 && grid[activePiece[i] + 10].available){
			continue
		}else{
			good = false;
			break;
		}
	}
	if(good){
		var newPiece = [activePiece[0]+10, activePiece[1]+10, activePiece[2]+10, activePiece[3]+10];
		for(j in activePiece){
			set(grid[activePiece[j] + 10], grid[activePiece[j]].bcolor, true, true);
			grid[activePiece[j] + 10].render();
		}
		for(k in activePiece){
			if(!in_array(activePiece[k] - 10, activePiece)){
				set(grid[activePiece[k]], 'background', false, true);
				grid[activePiece[k]].render();
			}
		}
		activePiece = newPiece;
	}else{
		for(x in activePiece){
			//if any part of the piece is touching the top row the game is over
			if(grid[activePiece[x]].y == 0){
				for(j in activePiece){
					grid[activePiece[j]].render();
				}
				running = false;
				endGame();
				return;
			}
		}
		
		for(i in activePiece){
			set(grid[activePiece[i]], grid[activePiece[i]].bcolor, false, false);
			grid[activePiece[i]].render();
		}
		var line;
		var filledLines = [];
		for(j in activePiece){ //check if there are any filled lines
			line = grid[activePiece[j]].y;
			filled = true;
			for(var i=0; i<10; i++){
				if(grid[line*10 + i].available){
					filled = false;
					break;
				}
			}
			if(filled && !in_array(line, filledLines)){
				filledLines.push(line);
			}
		}
		
		if(filledLines.length > 0){ //if there are filled lines, remove them and update statistics
			filledLines = filledLines.sort(function(a, b){return b - a;});
			for(x in filledLines){
				clearLine(filledLines[x] + (+x)); //convert x as it's a string for some reason...
			}
		
			if(filledLines.length == 1){
				score += 40*level;
			}else if(filledLines.length == 2){
				score += 100*level;
			}else if(filledLines.length == 3){
				score += 300*level;
			}else{
				score += 1200*level;
			}
			$('#scoreVal').html(score);
			$('#lineVal').html(linecount);
		}
		activePiece = false;
	}
}

function dropPiece(){
	shiftDown();
	if(activePiece == false){
		getNext();
		setPiece();
	}
}

function setGrid(){
	grid = [];
	for(var i=0; i < 20; i++){
		for(var j=0; j<10; j++){
			grid.push(new block(j, i));
		}
	}
}

function setPreview(){
	preview = [];
	for(var i=0; i < 6; i++){
		for(var j=0; j<5; j++){
			preview.push(new block(j, i));
		}
	}
}

//set a block object with the given properties
function set(block, bcolor, active, available){
	block.bcolor = bcolor;
	block.active = active;
	block.available = available;
}

//removes a single line from playing grid and shifts all blocks down a level
function clearLine(line){
	for(var i=((10*line) + 9); i>0; i--){
		if(grid[i].y != 0){
			set(grid[i], grid[i-10].bcolor, grid[i-10].active, grid[i-10].available);
			grid[i].render();
		}
	}
	if(++linecount % 10 == 0){
		$('#levelVal').html(++level);
		timeout -= 25;
	}
}

//render the main playing grid
function renderGrid(){
	for(var x=0; x<200; x++){
		grid[x].render();
	}
}

//render the preview grid
function renderPreview(){
	for(var x=0; x<30;x++){
		set(preview[x], 'background', false, true);
	}
	
	switch(next.btype){
		case 'sq':
			set(preview[getP(1,1)], next.bcolor, true, true);
			set(preview[getP(2,1)], next.bcolor, true, true);
			set(preview[getP(1,2)], next.bcolor, true, true);
			set(preview[getP(2,2)], next.bcolor, true, true);
			break;
		case 'rs':
			set(preview[getP(3,1)], next.bcolor, true, true);
			set(preview[getP(2,1)], next.bcolor, true, true);
			set(preview[getP(2,2)], next.bcolor, true, true);
			set(preview[getP(1,2)], next.bcolor, true, true);
			break;
		case 'ls':
			set(preview[getP(1,1)], next.bcolor, true, true);
			set(preview[getP(2,1)], next.bcolor, true, true);
			set(preview[getP(2,2)], next.bcolor, true, true);
			set(preview[getP(3,2)], next.bcolor, true, true);
			break;
		case 'rl':
			set(preview[getP(2,1)], next.bcolor, true, true);
			set(preview[getP(2,2)], next.bcolor, true, true);
			set(preview[getP(2,3)], next.bcolor, true, true);
			set(preview[getP(3,3)], next.bcolor, true, true);
			break;
		case 'll':
			set(preview[getP(2,1)], next.bcolor, true, true);
			set(preview[getP(2,2)], next.bcolor, true, true);
			set(preview[getP(2,3)], next.bcolor, true, true);
			set(preview[getP(1,3)], next.bcolor, true, true);
			break;
		case 'tee':
			set(preview[getP(1,2)], next.bcolor, true, true);
			set(preview[getP(2,2)], next.bcolor, true, true);
			set(preview[getP(3,2)], next.bcolor, true, true);
			set(preview[getP(2,3)], next.bcolor, true, true);
			break;
		case 'ln':
			set(preview[getP(2,1)], next.bcolor, true, true);
			set(preview[getP(2,2)], next.bcolor, true, true);
			set(preview[getP(2,3)], next.bcolor, true, true);
			set(preview[getP(2,4)], next.bcolor, true, true);
			break;
	}
	for(x=0; x<30; x++){
		preview[x].prev();
	}
}

//sets the active piece to the next generated piece
function getNext(){
	for(x in next.positions){
		set(grid[next.positions[x]], next.bcolor, true, true);
	}
	ctype = next.btype;
	cstate = 1;
	activePiece = next.positions;
}

//randomly choose a piece and create it on the grid
function setPiece(){
	var pieces = ['ls', 'rs', 'sq', 'rl', 'll', 'ln', 'tee']
	switch(pieces[Math.floor(Math.random() * 7)]){
		case 'sq':
			next.positions = [getB(3, 0), getB(4, 0), getB(3, 1), getB(4, 1)];
			next.btype = 'sq';
			next.bcolor = 'yellow';
			renderPreview();
			break;
		case 'ls':
			next.positions = [getB(2, 0), getB(3, 0), getB(3, 1), getB(4, 1)];
			next.btype = 'ls';
			next.bcolor = 'purple';
			renderPreview();
			break;
		case 'rs':
			next.positions = [getB(5, 0), getB(4, 0), getB(4, 1), getB(3, 1)];
			next.btype = 'rs';
			next.bcolor = 'green';
			renderPreview();
			break;
		case 'rl':
			next.positions = [getB(3, 0), getB(3, 1), getB(3, 2), getB(4, 2)];
			next.btype = 'rl';
			next.bcolor = 'orange';
			renderPreview();
			break;
		case 'll':
			next.positions = [getB(4, 0), getB(4, 1), getB(4, 2), getB(3, 2)];
			next.btype = 'll';
			next.bcolor = 'grey';
			renderPreview();
			break;
		case 'tee':
			next.positions = [getB(3, 0), getB(4, 0), getB(5, 0), getB(4, 1)];
			next.btype = 'tee';
			next.bcolor = 'red';
			renderPreview();
			break;
		case 'ln':
			next.positions = [getB(3, 0), getB(3, 1), getB(3, 2), getB(3, 3)];
			next.btype = 'ln';
			next.bcolor = 'blue';
			renderPreview();
			break;
	}
}

//rotate piece depending on it's current state and board position
function shiftState(){
	var newPiece = [];
	switch(ctype){
		case 'rs':
			if(cstate == 1){
				newPiece.push(getB(grid[activePiece[0]].x-2, grid[activePiece[0]].y), getB(grid[activePiece[1]].x-1, grid[activePiece[1]].y+1), activePiece[2], getB(grid[activePiece[3]].x+1, grid[activePiece[3]].y+1));
				if(free(newPiece)){
					shiftRSnake(newPiece);
					cstate = 2;
				}else{
					newPiece = activePiece;
				}
			}else{
				if(grid[activePiece[2]].x == 9){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x+2, grid[activePiece[0]].y), getB(grid[activePiece[1]].x+1, grid[activePiece[1]].y-1), activePiece[2], getB(grid[activePiece[3]].x-1, grid[activePiece[3]].y-1));
				if(free(newPiece)){
					shiftLSnake(newPiece);
					cstate = 1;
				}else{
					newPiece = activePiece;
				}
			}
			break;
		case 'ls':
			if(cstate == 1){
				newPiece.push(getB(grid[activePiece[0]].x+2, grid[activePiece[0]].y), getB(grid[activePiece[1]].x+1, grid[activePiece[1]].y+1), activePiece[2], getB(grid[activePiece[3]].x-1, grid[activePiece[3]].y+1));
				if(free(newPiece)){
					shiftRSnake(newPiece);
					cstate = 2;
				}else{
					newPiece = activePiece;
				}
			}else{
				if(grid[activePiece[2]].x == 0){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x-2, grid[activePiece[0]].y), getB(grid[activePiece[1]].x-1, grid[activePiece[1]].y+-1), activePiece[2], getB(grid[activePiece[3]].x+1, grid[activePiece[3]].y-1));
				if(free(newPiece)){
					shiftLSnake(newPiece);
					cstate = 1;
				}else{
					newPiece = activePiece;
				}
			}
			break;
		case 'rl':
			if(cstate == 1){
				if(grid[activePiece[1]].x == 0){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x-1, grid[activePiece[0]].y+1), activePiece[1], getB(grid[activePiece[2]].x+1, grid[activePiece[2]].y-1), getB(grid[activePiece[3]].x, grid[activePiece[3]].y-2));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 2;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 2){
				newPiece.push(getB(grid[activePiece[0]].x+1, grid[activePiece[0]].y+1), activePiece[1], getB(grid[activePiece[2]].x-1, grid[activePiece[2]].y-1), getB(grid[activePiece[3]].x-2, grid[activePiece[3]].y));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 3;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 3){
				if(grid[activePiece[1]].x == 9){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x+1, grid[activePiece[0]].y-1), activePiece[1], getB(grid[activePiece[2]].x-1, grid[activePiece[2]].y+1), getB(grid[activePiece[3]].x, grid[activePiece[3]].y+2));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 4;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 4){
				newPiece.push(getB(grid[activePiece[0]].x-1, grid[activePiece[0]].y-1), activePiece[1], getB(grid[activePiece[2]].x+1, grid[activePiece[2]].y+1), getB(grid[activePiece[3]].x+2, grid[activePiece[3]].y));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 1;
				}else{
					newPiece = activePiece;
				}
			}
			break;
		case 'll':
			if(cstate == 1){
				if(grid[activePiece[1]].x == 9){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x+1, grid[activePiece[0]].y+1), activePiece[1], getB(grid[activePiece[2]].x-1, grid[activePiece[2]].y-1), getB(grid[activePiece[3]].x, grid[activePiece[3]].y-2));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 2;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 2){
				newPiece.push(getB(grid[activePiece[0]].x-1, grid[activePiece[0]].y+1), activePiece[1], getB(grid[activePiece[2]].x+1, grid[activePiece[2]].y-1), getB(grid[activePiece[3]].x+2, grid[activePiece[3]].y));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 3;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 3){
				if(grid[activePiece[1]].x == 0){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x-1, grid[activePiece[0]].y-1), activePiece[1], getB(grid[activePiece[2]].x+1, grid[activePiece[2]].y+1), getB(grid[activePiece[3]].x, grid[activePiece[3]].y+2));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 4;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 4){
				newPiece.push(getB(grid[activePiece[0]].x+1, grid[activePiece[0]].y-1), activePiece[1], getB(grid[activePiece[2]].x-1, grid[activePiece[2]].y+1), getB(grid[activePiece[3]].x-2, grid[activePiece[3]].y));
				if(free(newPiece)){
					shiftRL(newPiece);
					cstate = 1;
				}else{
					newPiece = activePiece;
				}
			}
			break;
		case 'ln':
			if(cstate == 1){
				if(grid[activePiece[2]].x > 7 || grid[activePiece[2]].x == 0){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x+2, grid[activePiece[0]].y+2), getB(grid[activePiece[1]].x+1, grid[activePiece[1]].y+1), activePiece[2], getB(grid[activePiece[3]].x-1, grid[activePiece[3]].y-1));
				if(free(newPiece)){
					shiftLine(newPiece);
					cstate = 2;
				}else{
					newPiece = activePiece;
				}
			}else{
				newPiece.push(getB(grid[activePiece[0]].x-2, grid[activePiece[0]].y-2), getB(grid[activePiece[1]].x-1, grid[activePiece[1]].y-1), activePiece[2], getB(grid[activePiece[3]].x+1, grid[activePiece[3]].y+1));
				if(free(newPiece)){
					shiftLine(newPiece);
					cstate = 1;
				}else{
					newPiece = activePiece;
				}
			}
			break;
		case 'tee':
			if(cstate == 1){
				newPiece.push(getB(grid[activePiece[0]].x+1, grid[activePiece[0]].y+1), activePiece[1], getB(grid[activePiece[2]].x-1, grid[activePiece[2]].y-1), getB(grid[activePiece[3]].x+1, grid[activePiece[3]].y-1));
				if(free(newPiece)){
					shiftTee(newPiece);
					cstate = 2;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 2){
				if(grid[activePiece[1]].x == 0){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x+1, grid[activePiece[0]].y-1), activePiece[1], getB(grid[activePiece[2]].x-1, grid[activePiece[2]].y+1), getB(grid[activePiece[3]].x-1, grid[activePiece[3]].y-1));
				if(free(newPiece)){
					shiftTee(newPiece);
					cstate = 3;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 3){
				newPiece.push(getB(grid[activePiece[0]].x-1, grid[activePiece[0]].y-1), activePiece[1], getB(grid[activePiece[2]].x+1, grid[activePiece[2]].y+1), getB(grid[activePiece[3]].x-1, grid[activePiece[3]].y+1));
				if(free(newPiece)){
					shiftTee(newPiece);
					cstate = 4;
				}else{
					newPiece = activePiece;
				}
			}else if(cstate == 4){
				if(grid[activePiece[1]].x == 9){newPiece = activePiece; break;}
				newPiece.push(getB(grid[activePiece[0]].x-1, grid[activePiece[0]].y+1), activePiece[1], getB(grid[activePiece[2]].x+1, grid[activePiece[2]].y-1), getB(grid[activePiece[3]].x+1, grid[activePiece[3]].y+1));
				if(free(newPiece)){
					shiftTee(newPiece);
					cstate = 1;
				}else{
					newPiece = activePiece;
				}
			}
			break;
		default :
			newPiece = activePiece;
			break;
	}
	activePiece = newPiece;
}

function shiftRL(newPiece){
	set(grid[newPiece[0]], grid[activePiece[0]].bcolor, true, true);
	grid[newPiece[0]].render();
	set(grid[activePiece[0]], 'background', false, true);
	grid[activePiece[0]].render();
	set(grid[newPiece[2]], grid[activePiece[2]].bcolor, true, true);
	grid[newPiece[2]].render();
	set(grid[activePiece[2]], 'background', false, true);
	grid[activePiece[2]].render();
	set(grid[newPiece[3]], grid[activePiece[3]].bcolor, true, true);
	grid[newPiece[3]].render();
	set(grid[activePiece[3]], 'background', false, true);
	grid[activePiece[3]].render();
}

function shiftLine(newPiece){
	set(grid[newPiece[0]], grid[activePiece[0]].bcolor, true, true);
	grid[newPiece[0]].render();
	set(grid[activePiece[0]], 'background', false, true);
	grid[activePiece[0]].render();
	set(grid[newPiece[1]], grid[activePiece[1]].bcolor, true, true);
	grid[newPiece[1]].render();
	set(grid[activePiece[1]], 'background', false, true);
	grid[activePiece[1]].render();
	set(grid[newPiece[3]], grid[activePiece[3]].bcolor, true, true);
	grid[newPiece[3]].render();
	set(grid[activePiece[3]], 'background', false, true);
	grid[activePiece[3]].render();
}

function shiftTee(newPiece){
	set(grid[newPiece[0]], grid[activePiece[0]].bcolor, true, true);
	grid[newPiece[0]].render();
	set(grid[activePiece[0]], 'background', false, true);
	grid[activePiece[0]].render();
	set(grid[newPiece[2]], grid[activePiece[2]].bcolor, true, true);
	grid[newPiece[2]].render();
	set(grid[newPiece[3]], grid[activePiece[3]].bcolor, true, true);
	grid[newPiece[3]].render();
}

function shiftRSnake(newPiece){
	set(grid[newPiece[0]], grid[activePiece[0]].bcolor, true, true);
	grid[newPiece[0]].render();
	set(grid[activePiece[0]], 'background', false, true);
	grid[activePiece[0]].render();
	set(grid[newPiece[1]], grid[activePiece[1]].bcolor, true, true);
	grid[newPiece[1]].render();
	set(grid[activePiece[1]], 'background', false, true);
	grid[activePiece[1]].render();
	set(grid[newPiece[3]], grid[activePiece[3]].bcolor, true, true);
	grid[newPiece[3]].render();
}

function shiftLSnake(newPiece){
	set(grid[newPiece[0]], grid[activePiece[0]].bcolor, true, true);
	grid[newPiece[0]].render();
	set(grid[activePiece[0]], 'background', false, true);
	grid[activePiece[0]].render();
	set(grid[newPiece[1]], grid[activePiece[1]].bcolor, true, true);
	grid[newPiece[1]].render();
	set(grid[activePiece[1]], 'background', false, true);
	grid[activePiece[1]].render();
	set(grid[newPiece[3]], grid[activePiece[3]].bcolor, true, true);
	grid[newPiece[3]].render();
	set(grid[activePiece[3]], 'background', false, true);
	grid[activePiece[3]].render();
}

//handles key presses
function keyListener(e){
   if(running && activePiece != 'game_over'){
	   var evt=(e)?e:(window.event)?window.event:null;
	   if(evt.keyCode==37){
	      shiftLeft();
	   }else if(evt.keyCode==39){
		  shiftRight();
	   }else if(evt.keyCode==40){
		  dropPiece();
	   }else if(evt.keyCode==38){
		  shiftState();
	   }
   }
}

//start, restart, or pause the game depending on current state
function toggleTetris(){
	if(wloaded){	
		if(running){
	  		clearTimeout(instance);
			running = false;
			$(':button').val('Start');
	  	}else if(activePiece == 'game over'){
			$('#levelVal').html('1'); $('#lineVal, #scoreVal').text('0'); 
			init();
			loopGame();
			running = true;
			$(':button').val('Pause');
	  	}else{
	  		loopGame();
			running = true;
			$(':button').val('Pause');
	  	}
	}
}

//get array position in grid array from block coords
function getB(x, y){
	return (y == 0) ? x : (10*y) + x;
}

//get array position in preview array from block coords
function getP(x, y){
	return (y == 0) ? x : (5*y) + x;
}

function in_array(obj, array) {
	for ( var x = 0 ; x <= array.length ; x++ ) {
		if ( array[x] == obj ) return true;
	}
	return false;
}

function endGame(){
	clearTimeout(instance);
	activePiece = 'game over';
	$('#gameOver').show();
	$(':button').val('Start');
}

function free(piece){
	if((+Math.max.apply( Math, piece )) < (+199) && (+Math.min.apply( Math, piece )) > (+0)){
		for(i in piece){
			if(!grid[piece[i]].available){
				return false;
			}
		}
		return true;
	}else{
		return false;
	}
	
	
}
