// Constants - lots of tweaking material

var BASELINE = 400;
var TONY_VOFFSETMULT = 24;		// Offset per level completed
var TONY_MOVE_AMOUNT = 15;
var TONY_VDROP_INIT = 25;		// Vertical tony drop
var TONY_VDROP_INC = 5;			// Extra drop per xx levels completed
var TONY_SCREENS_BEFORE_BACK_TO_TOP = 6;// xx as above    --
var NO_TONYS = 24;
var MISSILE_WIDTH = 3;
var MISSILE_HEIGHT = 15;
var SCREENLEFT = 0;
var SCREENRIGHT = 570;
var SCREENTOP = 20;
var BASE_WIDTH = 30;
var BASE_HEIGHT = 15;
var HALF_BASE_WIDTH = BASE_WIDTH / 2;
var BASERIGHT = SCREENRIGHT - BASE_WIDTH;
var BASELEFT = SCREENLEFT + 20;
var TONYLEFT = 10;
var NO_BOMBS = 4;
var BOMB_HEIGHT = 15;
var BOMB_WIDTH = 4;
var BOMB_PROBABILITY = 0.1;		// 1 in 10
var BOMB_LAYER_OFFSET = NO_TONYS;
var BOMBCHECK = BASELINE + 3;		// Forget about the turret bit
var BOMBSTOP = BASELINE + BASE_HEIGHT;	// bottom of base
var MISSILE_X_OFFSET = 14;
var TONYRIGHT = SCREENRIGHT - (TONY_WIDTH - 10);
var INVADELINE = BASELINE - TONY_HEIGHT;

var IMAGE_BASEHIT = "gfx/invaders/basehit.gif";
var IMAGE_BASE = "gfx/invaders/base.gif";
var IMAGE_TONYHIT = "gfx/invaders/tonysplat.gif";

/* Game status */
var STATUS_GAME_OVER = 0;
var STATUS_LOSE_A_LIFE = 1;
var STATUS_PLAYING = 2;
var STATUS_DEMO = 3;
var STATUS_NEXT_WAVE = 4;

/* Section Status */
var SECTION_PAUSED = 0;
var SECTION_RESET = 1;
var SECTION_RUNNING = 2;

/* Global vars */
var docObjects, gameStatus, modeStatus;
var tony_x, tony_y, tony_a;
var bomb_x, bomb_y, bomb_a;
var missile_x, missile_y, missile_a;
var base_x = 250;
var base_move;
var tonyImg, basehitImg, baseImg;
var baseObject, missileObject;
var tonys_hit, tony_to_move, tony_direction;
var tonyImg = new Image();
var tonyhitImg = new Image();
var basehitImg = new Image();
var baseImg = new Image();
var i_tony = new Array (NO_TONYS);
var no_active_bombs;
var tony_vdrop = TONY_VDROP_INIT;
var bombSection, tonySection, baseSection, missileSection;
var lives, level, yourScore;
var hiScore, gameOver, topScore;
var altern8, lastMousePosX;
var timeNow;
var oldStopWatch;

/* "Class" for initial tony position */
function p_data(x, y, a)
{
	this.x = x;
	this.y = y;
	this.active = a;
}

/* Run once on page load */
function init()
{
	timeNow = new Date()
	oldStopWatch = timeNow.getTime();

	hiScore = document.getElementById ("hiscore");
	gameOver = document.getElementById ("gameover");
	topScore = document.getElementById ("topscore");
	hidePopups();

	var gameWindow = document.getElementById ("playarea");
	docObjects = gameWindow.getElementsByTagName ("div");
	
	tonyImg.src = document.images.ti0.src;
	basehitImg.src = IMAGE_BASEHIT;
	baseImg.src = IMAGE_BASE;
	tonyhitImg.src = IMAGE_TONYHIT;
	
	baseObject = docObjects ['l_base'];
	missileObject = docObjects ['l_missile'];
	
	/* Set up initial positions */
	i_tony [0] = new p_data (20, 30, 1);
	i_tony [1] = new p_data (20, 80, 1);
	i_tony [2] = new p_data (20, 130, 1);
	i_tony [3] = new p_data (20, 180, 1);
	i_tony [4] = new p_data (85, 30, 1);
	i_tony [5] = new p_data (85, 80, 1);
	i_tony [6] = new p_data (85, 130, 1);
	i_tony [7] = new p_data (85, 180, 1);
	i_tony [8] = new p_data (150, 30, 1);
	i_tony [9] = new p_data (150, 80, 1);
	i_tony [10] = new p_data (150, 130, 1);
	i_tony [11] = new p_data (150, 180, 1);
	i_tony [12] = new p_data (215, 30, 1);
	i_tony [13] = new p_data (215, 80, 1);
	i_tony [14] = new p_data (215, 130, 1);
	i_tony [15] = new p_data (215, 180, 1);
	i_tony [16] = new p_data (280, 30, 1);
	i_tony [17] = new p_data (280, 80, 1);
	i_tony [18] = new p_data (280, 130, 1);
	i_tony [19] = new p_data (280, 180, 1);
	i_tony [20] = new p_data (345, 30, 1);
	i_tony [21] = new p_data (345, 80, 1);
	i_tony [22] = new p_data (345, 130, 1);
	i_tony [23] = new p_data (345, 180, 1);
	
	tony_x = new Array (NO_TONYS);
	tony_y = new Array (NO_TONYS);
	tony_a = new Array (NO_TONYS);
	bomb_x = new Array (NO_BOMBS);
	bomb_y = new Array (NO_BOMBS);
	bomb_a = new Array (NO_BOMBS);

	modeStatus = STATUS_DEMO;
	altern8 = 0;

	window.onkeydown = keyPress;
	window.onkeyup = keyRelease;
	window.onmousemove = mouseControl;
	
	setTimeout('fastClock()', 28);
	setTimeout('fastClock()', 42);
	
	document.getElementById ("startwindow").style.visibility = "visible";
	document.forms.scoreboard.yourscore.value = "0";
}

/* All the game controls are done in here */
function fastClock()
{
	timeNow = new Date();
	stopWatch = timeNow.getTime();
	diff = stopWatch - oldStopWatch;
	if (diff <= 0) {
		setTimeout("fastClock()", 14);	
		}

	else {
		setTimeout("fastClock()", 28);
		oldStopWatch = stopWatch;

		switch (gameStatus) {
			case STATUS_PLAYING:
				if ((altern8 = 1 - altern8) == 0) tonyMove();
				break;
	
			case STATUS_LOSE_A_LIFE:
				bombSection = SECTION_PAUSED;
				tonySection = SECTION_PAUSED;
				baseSection = SECTION_PAUSED;
	//			missileSection = SECTION_PAUSED;
				resetBombs();
				loseLife();
				break;
				
			case STATUS_GAME_OVER:
				bombSection = SECTION_PAUSED;
				tonySection = SECTION_PAUSED;
				baseSection = SECTION_PAUSED;
				missileSection = SECTION_PAUSED;
				break;
				
			case STATUS_NEXT_WAVE:
				tonySection = SECTION_PAUSED;
				resetTonys();
				setTimeout ("restartGame()", 1000);
				gameStatus = STATUS_PLAYING;
				break;
		}
		baseMove();
		bombMove();
		missileMove();
	}
}

function resetVars()
{
	gameStatus = STATUS_PLAYING;
	no_active_bombs = 0;
	missile_a = 0;
	tonys_hit = NO_TONYS;
	level = 0;
	lives = 3;
	yourScore = 0;
	document.forms.scoreboard.yourscore.value = "0";
	docObjects['spare_base1'].style.visibility = "visible";
	docObjects['spare_base2'].style.visibility = "visible";

}

function tonyHit(hitNo)
{
	tony_a [hitNo] = 0;
	eval("document.images.ti"+hitNo+".src = IMAGE_TONYHIT");
	setTimeout ("restoreTony("+hitNo+")", 60);
	yourScore += 10;
	document.forms.scoreboard.yourscore.value = yourScore;
	tonys_hit--;

	if (tonys_hit == 0) {
		level++;
		if (level == TONY_SCREENS_BEFORE_BACK_TO_TOP) {
			level = 0;
			tony_vdrop += TONY_VDROP_INC;
		}

		setTimeout ("gameStatus = STATUS_NEXT_WAVE", 1000);
	}
	
	resetMissile();
}

function restoreTony(hitNo)
{
	docObjects [hitNo].style.visibility = "hidden";
}

function loseLife()
{
	document.images.i_base.src = IMAGE_BASEHIT;

	lives--;
	if (lives == 0) {
		endGame ();
		gameStatus = STATUS_GAME_OVER;
		return;
	}
	setTimeout ("baseObject.style.visibility = 'hidden'", 1000);
	setTimeout ("resetBase()", 2000);
	setTimeout ("restartGame()", 3000);
	gameStatus = STATUS_PLAYING;
}

function endGame()
{
	bombSection = SECTION_PAUSED;
	tonySection = SECTION_PAUSED;
	baseSection = SECTION_PAUSED;
	missileSection = SECTION_PAUSED;

	if (yourScore > TopScore) {
		setTimeout ('popupTopScore()', 1000);
		scorestring = endgame(yourScore);
		document.forms.topscore.tscore.value = yourScore;
		document.forms.topscore.encscore.value = scorestring;
		}
	else if (yourScore > BottomScore) {
		setTimeout ('popupHiScore()', 1000);
		scorestring = endgame(yourScore);
		document.forms.hiscore.hscore.value = yourScore;
		document.forms.hiscore.encscore.value = scorestring;
		}
	else {
		setTimeout ('popupGameOver()', 1000);
		document.forms.gameover.gameoverscore.value = yourScore;
	}
}

function start()
{
	resetVars();
	hidePopups();
	resetBase();
	resetBombs();
	resetTonys();
	resetMissile();
	setTimeout("restartGame()", 2000);
}

function stoppit()
{
	bombSection = SECTION_PAUSED;
	tonySection = SECTION_PAUSED;
	baseSection = SECTION_PAUSED;
	missileSection = SECTION_PAUSED;
	document.forms.scoreboard.yourscore.value = "Stopped";
	gameStatus = STATUS_GAME_OVER;
	
	setTimeout("wait()", 1000);	
}

function wait()
{
	hidePopups();
	document.getElementById ("startwindow").style.visibility = "visible";
}

function restartGame()
{
	if (lives == 0) {
		endGame ();
		gameStatus = STATUS_GAME_OVER;
		return;
	}

	bombSection = SECTION_RUNNING;
	tonySection = SECTION_RUNNING;
	baseSection = SECTION_RUNNING;
	missileSection = SECTION_RUNNING;
}

function resetBase()
{
	if (lives == 2) docObjects ['spare_base2'].style.visibility = "hidden";
	else if (lives == 1) docObjects ['spare_base1'].style.visibility = "hidden";
	baseObject.style.visibility = "visible";
	document.images.i_base.src = IMAGE_BASE;
	baseSection = SECTION_RUNNING;
	missileSection = SECTION_RUNNING;
}

/* Returns all bombs to an inactive state */
function resetBombs()
{
	var i;
	
	for (i = 0; i < NO_BOMBS; i++) {
		bomb_a [i] = 0;
		docObjects [BOMB_LAYER_OFFSET + i].style.visibility = "hidden";
	}
	no_active_bombs = 0;
}

/* Returns all tonys to start point for that level */
function resetTonys()
{
	for (i = 0; i < NO_TONYS; i++) {
		eval("document.images.ti"+i+".src = tonyImg.src");
		tony_x [i] = i_tony [i].x;
		tony_y [i] = i_tony [i].y + (level * TONY_VOFFSETMULT);
		tony_a [i] = 1;
		docObjects [i].style.top = tony_y [i]+"px"; 
		docObjects [i].style.left = tony_x [i]+"px";
		docObjects [i].style.visibility = "visible";
		}
	
	tonys_hit = NO_TONYS;
	tony_to_move = NO_TONYS-1;
	tony_direction = 1;
}

function resetMissile()
{
	missileObject.style.visibility = "hidden";
	missile_a = 0;
}

function keyPress(e)
{
	var thiskey;

	/* So it works with IE */
	if (!e) e = event;

	thiskey = String.fromCharCode (e.keyCode);
	thiskey = thiskey.toLowerCase ();
	if (thiskey == "z") base_move = -1;
	if (thiskey == "x") base_move = +1;
	if (thiskey == "m") fire();
}

function keyRelease(e)
{
	var thiskey;

	if (!e) e = event;

	thiskey = String.fromCharCode (e.keyCode);
	thiskey = thiskey.toLowerCase ();
	if (thiskey == "z" && base_move == -1) base_move = 0;
	if (thiskey == "x" && base_move == +1) base_move = 0;
}

function mouseControl(e)
{
	if (document.forms.controls.UseMouse.checked != true) return;
	if (!e) e = event;
	lastMousePosX = e.clientX - 187;
}


/* Collision detection */
function r_detect(o1_l, o1_r, o1_t, o1_b, o2_l, o2_r, o2_t, o2_b)
{
	if (o2_r < o1_l) return 0;
	if (o2_l > o1_r) return 0;
	if (o2_t > o1_b) return 0;
	if (o2_b < o1_t) return 0;
	return 1;
}

function missileMove()
{
	if (missile_a == 0 || missileSection != SECTION_RUNNING) return;
	
	missile_y -= 9;
	missileObject.style.top = missile_y+"px";
	if (missile_y < SCREENTOP) {
		missileObject.style.visibility = "hidden";
		missile_a = 0;
	}

	// Collision detect
	for (i = 0; i < NO_TONYS; i++) if (tony_a [i] == 1) {
		tonyXpos = tony_x [i];
		tonyYpos = tony_y [i];

		if (tonyXpos+TONY_WIDTH > missile_x && tonyXpos < missile_x+MISSILE_WIDTH && tonyYpos < missile_y+MISSILE_HEIGHT && tonyYpos+TONY_HEIGHT > missile_y) {
			tonyHit(i);
			return;
		}
	}
}

function baseMove()
{
	if (document.forms.controls.UseMouse.checked == true) {
		base_move = 0;
		if ((lastMousePosX - HALF_BASE_WIDTH)+1 < base_x) base_move = -1;
		if ((lastMousePosX - HALF_BASE_WIDTH)-1 > base_x) base_move = 1;
	}

	if (baseSection != SECTION_RUNNING) return;
	if (base_move == -1 && base_x > BASELEFT)  base_x -= 2;
	if (base_move == 1 && base_x < BASERIGHT) base_x += 2;
	baseObject.style.left = base_x+"px";
}

function bombMove()
{
	var i;
	var bombtop, bombleft, bombbottom;

	if (bombSection != SECTION_RUNNING) return;
	
	for (i = 0; i < NO_BOMBS; i++) if (bomb_a [i] == 1) {
		bombtop = bomb_y [i];
		bombleft = bomb_x [i];
		bombtop += 4;
		bomb_y [i] = bombtop;
		bombbottom = bombtop + BOMB_HEIGHT;
	
		if (bombbottom > BOMBCHECK) {
			if (r_detect (bombleft, bombleft+BOMB_WIDTH, bombtop, bombtop+BOMB_HEIGHT, base_x, base_x+BASE_WIDTH, BOMBCHECK, BOMBSTOP)) {
				gameStatus = STATUS_LOSE_A_LIFE;
			}
			if (bombbottom > BOMBSTOP) {
				bomb_a [i] = 0;
				docObjects [BOMB_LAYER_OFFSET + i].style.visibility = "hidden";
				no_active_bombs--;
			}
		}

		docObjects [BOMB_LAYER_OFFSET + i].style.top = bombtop+"px";
	}
}

function tonyMove()
{
	// Get the one to move next.  If going right/down start at end and go down, 
	// otherwise start at 0 and go up.
	//
	// tony_direction: 1 ->  2 v  3 <-  4 v
	var i;
	var tonyXpos;
	var tonyYpos;
	var start_tony;
	
	if (tonys_hit == 0 || tonySection != SECTION_RUNNING) return;
	
	/* We've come to the end of the list of tonys so... */
	if (tony_to_move < 0) {
	
		/* Check to see if they are going down.  Change to sideways movement if so */
		if (tony_direction == 2 || tony_direction == 4) tony_direction = 5 - tony_direction;
	
		/* Check to see if any of them are at the end of the screen */
		else for (i = 0; i < NO_TONYS; i++) {
			tonyXpos = tony_x [i];
			if (tony_a [i] == 1 && ((tonyXpos >= TONYRIGHT && tony_direction == 1) || (tonyXpos <= TONYLEFT && tony_direction == 3))) {
				tony_direction++;
				break;
			}
		}
	
		/* Reset the count to the first tony */	
		tony_to_move = NO_TONYS-1;
	}

	start_tony = tony_to_move;
	
	/* Find the next available tony */
	while (tony_a [tony_to_move] == 0) {
		tony_to_move--;
		if (tony_to_move == start_tony) return;	// Don't get trapped
		
		/* We've come to the end of the tonys, so check direction as above */
		if (tony_to_move < 0) {
			if (tony_direction == 2 || tony_direction == 4) tony_direction = 5 - tony_direction;
			else {
				for (i = 0; i < NO_TONYS; i++) {
					tonyXpos = tony_x [i];
					if (tony_a [i] == 1 && ((tonyXpos >= TONYRIGHT && tony_direction == 1) || (tonyXpos <= TONYLEFT && tony_direction == 3))) {
						tony_direction++;
						break;
					}
				}
			}
			tony_to_move = NO_TONYS-1;
		}
	}

	if (tony_direction == 1) {
		tony_x [tony_to_move] += TONY_MOVE_AMOUNT;
		docObjects [tony_to_move].style.left = tony_x [tony_to_move]+"px";
		tonyXpos = tony_x [tony_to_move];
		tonyYpos = tony_y [tony_to_move];
		if (no_active_bombs < NO_BOMBS && Math.random () < BOMB_PROBABILITY) doBomb (tonyXpos, tonyYpos);
		tony_to_move--;
	}
	
	else if (tony_direction == 3) {
		tony_x [tony_to_move] -= TONY_MOVE_AMOUNT;
		docObjects [tony_to_move].style.left = tony_x [tony_to_move]+"px";
		tonyXpos = tony_x [tony_to_move];
		tonyYpos = tony_y [tony_to_move];
		if (no_active_bombs < NO_BOMBS && Math.random () < BOMB_PROBABILITY) doBomb (tonyXpos, tonyYpos);
		tony_to_move--;
	}
	
	else if (tony_direction == 4 || tony_direction == 2) {
		tony_y [tony_to_move] += tony_vdrop;
		docObjects [tony_to_move].style.top = tony_y [tony_to_move]+"px";
		tonyXpos = tony_x [tony_to_move];
		tonyYpos = tony_y [tony_to_move];
		if (no_active_bombs < NO_BOMBS && Math.random () < BOMB_PROBABILITY) doBomb (tonyXpos, tonyYpos);
	
		if (tonyYpos >= INVADELINE) {
			/* Set game status flag */
			endGame();
			gameStatus = STATUS_GAME_OVER;
		}
		tony_to_move--;
	}
}

	
function fire()
{
	if (missile_a == 1 || baseSection != SECTION_RUNNING) return;
	missile_a = 1;
	missile_y = BASELINE - MISSILE_HEIGHT;
	missile_x = base_x + MISSILE_X_OFFSET;
	missileObject.style.left = missile_x+"px";
	missileObject.style.top = missile_y+"px";
	missileObject.style.visibility = "visible";
}

function doBomb(drop_positionx, drop_positiony)
{
	var i;
	var bdrop_positionx;
	var bdrop_positiony;
	var thisBomb;

	for (i = 0; i < NO_BOMBS; i++) if (bomb_a [i] == 0) {
		bdrop_positionx = drop_positionx + Math.round (TONY_WIDTH/2);
		bdrop_positiony = drop_positiony + TONY_HEIGHT;

		thisBomb = BOMB_LAYER_OFFSET + i;
		bomb_x [i] = bdrop_positionx;
		bomb_y [i] = bdrop_positiony;

		docObjects [thisBomb].style.left = bdrop_positionx+"px";
		docObjects [thisBomb].style.top = bdrop_positiony+"px";
		docObjects [thisBomb].style.visibility = "visible";

		bomb_a [i] = 1;
		no_active_bombs++;
		break;
	}
}

function popupHiScore()
{
	hiScore.style.visibility = "visible";
	document.forms.hiscore.name.focus();
}

function popupTopScore()
{
	topScore.style.visibility = "visible";
	document.forms.topscore.name.focus();
}

function popupGameOver()
{
	gameOver.style.visibility = "visible";
}

function hidePopups()
{
 	topScore.style.visibility = "hidden";
	hiScore.style.visibility = "hidden";
	gameOver.style.visibility = "hidden";
	document.getElementById ("startwindow").style.visibility = "hidden";
	return true;
}	

function endgame (yourscore)
{
	// alert ("Game over.  You scored " + yourscore);
	
	r1 = Math.floor (Math.random () * 16 + 75);
	r2 = Math.floor (Math.random () * 16 + 75);
	r3 = Math.floor (Math.random () * 16 + 75);
	r4 = Math.floor (Math.random () * 16 + 75);
	r5 = Math.floor (Math.random () * 16 + 75);
	
	if (yourscore < 10) score3digit = "0000" + yourscore;
	else if (yourscore < 100) score3digit = "000" + yourscore;
	else if (yourscore < 1000) score3digit = "00" + yourscore;
	else if (yourscore < 10000) score3digit = "0" + yourscore
	else score3digit = "" + yourscore;
	
	s1 = r1 - (score3digit.charCodeAt (0) - 48);
	s2 = r2 - (score3digit.charCodeAt (1) - 48);
	s3 = r3 - (score3digit.charCodeAt (2) - 48);
	s4 = r4 - (score3digit.charCodeAt (3) - 48);
	s5 = r5 - (score3digit.charCodeAt (4) - 48);
	
	c1 = (Math.floor ((s1 * r1) % 26)) + 65;
	c2 = (Math.floor ((s2 * r2) % 26)) + 65;
	c3 = (Math.floor ((s3 * r3) % 26)) + 65;
	c4 = (Math.floor ((s4 * r4) % 26)) + 65;
	c5 = (Math.floor ((s5 * r5) % 26)) + 65;
	
	scorestring = String.fromCharCode (c4, c5, r1, c2, s3, s4, s5, c1, s2, r3, r4,r5, s1, r2, c3);
	return scorestring;
}

