// falling_fours.js

// The main code of the falling fours game

// A game much like tetris, only under a different name because the tetris is tradmarked

// Author:  Gabe Greve



var points;

var lines;

var level;

var timestep;

var piece;

var nextPiece;

var gameIsRunning = false;

var isFastDown;

var isPaused;

var statistics;



var gBLOCKS = 4;

var gROWS = 24;

var gCOLS = 10;



function startGame()

{

	if(!gameIsRunning) {

        // hide stuff

        var element = document.getElementById("instructionsButton");

        element.style.height = "0px";

        hideInstructions();

        hideGameOver();



		// reset game variables

		points = 0;

		lines = 0;

		level = 0;

		element = document.getElementById("points");

		element.innerHTML = points;

		element = document.getElementById("lines");

		element.innerHTML = lines;

		element = document.getElementById("level");

		element.innerHTML = level;

		timestep = 1024;

		piece = new Piece(randomNumber());

		nextPiece = new Piece(randomNumber());

		isFastDown = false;

		isPaused = false;

		statistics = new Array(0, 0, 0, 0, 0, 0, 0);

		for ($i=0; $i<7; $i++)

		{

			element = document.getElementById("piece" + $i);

			element.innerHTML = 0;

		}

		

		initBoard();

		place(); // place piece calls the first move function

		showNextPiece();

		gameIsRunning = true;

	}

}



function randomNumber() // returns a random number 0-6

{

	return Math.round(Math.random()*100)%7;

}



function initBoard()

{

	for(var i = 0; i < gROWS; i++) // 24 rows

	{

		for(var j = 0; j < gCOLS; j++) // 10 columns

		{

			var element = document.getElementById("index"+i+"_"+j);

			element.style.backgroundImage="url(images/background.png)";

		}

	}



}



// places the piece for the first time

function place()

{

	// update statistics

	var element = document.getElementById("piece" + piece.id);

	element.innerHTML = ++statistics[piece.id];

	

	var positionArray = piece.getPositionArray();

	var color = piece.getColor();

	// place piece

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

		element.style.backgroundImage="url(images/"+color+".png)";

	}

	

	setTimeout("moveDown(true);", timestep);

}



// clears and shows the next piece in the next display

function showNextPiece()

{

	// clear next display

	for(var i = 0; i < 4; i++) // 4 rows

	{

		for(var j = 0; j < 2; j++) // 2 columns

		{

			var element = document.getElementById("next"+i+"_"+j);

			element.style.backgroundImage="url(images/background.png)";

		}

	}

	var positionArray = nextPiece.getPositionArray();

	var color = nextPiece.getColor();

	// show next piece

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		var element = document.getElementById("next"+pos.getX()+"_"+(pos.getY()-4));

		element.style.backgroundImage="url(images/"+color+".png)";

	}

}



// moves a piece down one block

function moveDown(doTimestep)

{

	if (!isPaused)

	{

		var positionArray = piece.getPositionArray();

		var color = piece.getColor();

		

		// check if piece can be moved

		for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

		{

			var pos = positionArray[i];

			if (pos.getX() == gROWS-1)

			{

				if (doTimestep)

				{

					imbedPiece();

				}

				return false;

			}

		}

		for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

		{

			var pos = positionArray[i];

			var element = document.getElementById("index"+(pos.getX()+1)+"_"+pos.getY());

			if ("url(images/background.png)" != element.style.backgroundImage &&

				"url(images/"+color+".png)" != element.style.backgroundImage)

			{

				if (doTimestep)

				{

					imbedPiece();

				}

				return false;

			}

		}

		

		var newPositionArray = new Array();

		// move piece

		for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

		{

			var pos = positionArray[i];

			newPositionArray[i] = new Position(pos.getX()+1, pos.getY());

		}

		for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

		{

			var pos = positionArray[i];

			var element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

			element.style.backgroundImage="url(images/background.png)";

		}

		for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

		{

			var pos = newPositionArray[i];

			var element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

			element.style.backgroundImage="url(images/" + color + ".png)";

		}

		piece.setPositionArray(newPositionArray);

		

		if (doTimestep && !isPaused)

		{

			if (isFastDown)

			{

				setTimeout("moveDown(true);", timestep*.25);

			}

			else

			{

				setTimeout("moveDown(true);", timestep);

			}

		}

		return true;

	}

}



// when piece hits the bottom it needs to be imbedded onto the stack of blocks

function imbedPiece(){

	var positionArray = piece.getPositionArray();

	var color = piece.getColor();

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		var element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

        if (element.className == "invisibleCell"){

            // Game is over

			gameOver();

        }

		element.style.backgroundImage = "url(images/dark" + color + ".png)";

	}

	removeLines();

    if (gameIsRunning){

        piece = nextPiece;

        nextPiece = new Piece(randomNumber());

        place();

        showNextPiece();

    }

}



// when the block make a complete row they need to be removed

function removeLines()

{

	var completeLines = new Array();

	for (var i = gROWS-1; i >= 0; i--)

	{

		if (isLine(i)) 

		{

			lines++;

			completeLines.push(i);

		}

	}

	switch(completeLines.length)

	{

	case 1:

		points += 1*(level+1);

		break;

	case 2:

		points += 3*(level+1);

		break;

	case 3:

		points += 6*(level+1);

		break;

	case 4:

		points += 10*(level+1);

		break;

	default: // ignore default because it does not matter

		break;

	}

	for (var i = 0; i < completeLines.length; i++)

	{

		shiftDown(completeLines[i]+i);

	}

	

	// update line and point totals

	if (completeLines.length > 0)

	{

		var element = document.getElementById("points");

		element.innerHTML = points;

		element = document.getElementById("lines");

		element.innerHTML = lines;

		if ((lines - lines%17)/ 17 > level)

		{

			level++;

			timestep *= .75;

			element = document.getElementById("level");

			element.innerHTML = level;

		}

	}

}



// for a given row number checks to se if it is a complete line

function isLine(i)

{

	for (var j = 9; j >= 0; j--)

	{

		var element = document.getElementById("index"+i+"_"+j);

		if ("url(images/background.png)" == element.style.backgroundImage)

		{

			return false;

		}

	}

	return true;

}



// move all the blocks above freshly removed line down

function shiftDown(line)

{

	for (var i = line; i > 0; i--)

	{

		for (var j = 0; j < gCOLS; j++)

		{

			var element = document.getElementById("index"+i+"_"+j);

			var elementAbove = document.getElementById("index"+(i-1)+"_"+j);

			element.style.backgroundImage = elementAbove.style.backgroundImage;

		}

	}

}



// figure out what key was pressed make the appropriate

function keyPress(event)

{

	var unicode=event.keyCode? event.keyCode : event.charCode;

	if (gameIsRunning && !isPaused)

	{

		switch(unicode)

		{

		case 32: // space bar

			isFastDown = true;

			break;

		case 37: // left arrow

		case 65: // 'a' key

			moveLeft();

			break;

		case 38: // up arrow

		case 87: // 'w' key

			piece.rotate();

			break;

		case 39: // right arrow

		case 68: // 'd' key

			moveRight();

			break;

		case 40: // down arrow

		case 83: // 's' key

			while(moveDown(false));

			break;

        case 19: // 'pause' key

        case 80: // 'p' key

            // pause the game

            pause();

            break;

		default: // ingore default case because it does not matter

			break;

		}

	}

	else if (unicode == 19 || unicode == 80) // 'pause' or 'p' key

	{

		// resume the game

        pause();

	}

}



// when key is released take appropriate action

function keyRelease(event)

{

	if (gameIsRunning && !isPaused)

	{

		var unicode=event.keyCode? event.keyCode : event.charCode;

		if (unicode == 32) // space bar

		{

			isFastDown = false;

		}

	}

}



// move piece to the left

function moveLeft()

{

	var positionArray = piece.getPositionArray();

	var color = piece.getColor();

	

	// check if piece can be moved

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		if (pos.getY() == 0)

		{

			return;

		}

	}

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		var element = document.getElementById("index"+pos.getX()+"_"+(pos.getY()-1));

		if ("url(images/background.png)" != element.style.backgroundImage &&

			"url(images/"+color+".png)" != element.style.backgroundImage)

		{

			return;

		}

	}



	var newPositionArray = new Array();

	// move piece

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		newPositionArray[i] = new Position(pos.getX(), pos.getY()-1);

	}

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		var element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

		element.style.backgroundImage="url(images/background.png)";

	}

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = newPositionArray[i];

		var element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

		element.style.backgroundImage="url(images/" + color + ".png)";

	}

	piece.setPositionArray(newPositionArray);

}



// move piece to the right

function moveRight()

{

	var positionArray = piece.getPositionArray();

	var color = piece.getColor();

	

	// check if piece can be moved

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		if (pos.getY() == 9)

		{

			return;

		}

	}

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		var element = document.getElementById("index"+pos.getX()+"_"+(pos.getY()+1));

		if ("url(images/background.png)" != element.style.backgroundImage &&

			"url(images/"+color+".png)" != element.style.backgroundImage)

		{

			return;

		}

	}



	var newPositionArray = new Array();

	// move piece

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		newPositionArray[i] = new Position(pos.getX(), pos.getY()+1);

	}

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = positionArray[i];

		var element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

		element.style.backgroundImage="url(images/background.png)";

	}

	for (var i = 0; i < gBLOCKS; i++) // 4 blocks per piece

	{

		var pos = newPositionArray[i];

		var element = document.getElementById("index"+pos.getX()+"_"+pos.getY());

		element.style.backgroundImage="url(images/" + color + ".png)";

	}

	piece.setPositionArray(newPositionArray);

}



// toggle the pause to freeze and unfreeze the game

function pause()

{

	if (isPaused)

	{

		isPaused = false;

		moveDown(true);

	}

	else 

	{

		isPaused = true;

	}

}



// hide game over when

function hideGameOver()

{

	var element = document.getElementById("gameOver");

	element.style.height = "0px";

}



// check if a name is present to record high score

function doSubmit()

{

	return false;

/*	var element = document.getElementById("playerName");

	

	if (element.value == "")

	{

		// make game over div invisible

		element = document.getElementById("gameOver");

		element.style.height = "0px";

		

		// restore start button

		var element = document.getElementById("startButton");

		element.innerHTML = "<img src=\"images/startGame.png\" onclick=\"startGame()\"" +

			"onmouseover=\"this.src='images/startGameOver.png';\"" +

			"onmouseout=\"this.src='images/startGame.png';\" />";

		

		return false;

	}

	else

	{

		return true;

	}*/

}



function gameOver()

{

	gameIsRunning = false;

			

	var element = document.getElementById("finalPoints");

	element.innerHTML = points;

	element = document.getElementById("finalLines");

	element.innerHTML = lines;

	

	// Set the hidden points field

	//element = document.getElementById("pointsEarned");

	//element.value = points;

	

	// check browsers since game does not work in all browsers

	var browser = BrowserDetect.browser;

	if (browser != "Firefox" && browser != "Explorer")

	{

		element = document.getElementById("gameOver");

		element.innerHTML = "Sorry if falling fours does not work in your browser. Falling fours works in either Microsoft Internet Explorer or Mozilla Firefox if you want to give it a try.";

	}

	

	// make game over div visible

	element = document.getElementById("gameOver");

	element.style.height = "200px";

    element = document.getElementById("instructionsButton");

    element.style.height = "18px";



}



function instrucitons()

{

    var element = document.getElementById("instructions");

    element.style.height = "400px";

    element.style.padding = "10px";

}



function hideInstructions()

{

    var element = document.getElementById("instructions");

    element.style.height = "0px";

    element.style.padding = "0px";

}
