/***********************************************************/
/* Battleship made by Bjarne Fich                          */
/* www.rednebula.com                                       */
/***********************************************************/
/* Start game with:                                        */
/*	battleShipsBuildMaps(horizontal, cellsize, cols, rows);*/
/*	battleShipsNewGame();                                  */
/*	battleShipsUpdateMaps();                               */
/* Ex:                                                     */
/*	battleShipsBuildMaps(true, 20, 8, 8);                  */
/*	battleShipsNewGame();                                  */
/*	battleShipsUpdateMaps();                               */
/***********************************************************/

var battleShipsMapCellSize = 10;
var battleShipsMapSizeX = 10;
var battleShipsMapSizeY = 10;
var battleShipsTimerID = 0;

var battleShipsMapData = new Array();
var battleShipsMapDataPrCell = 4;

var gameOver = false;

var battleShipsShipDef = new Array(
"Battleship","#00a000","#00a000",
"     ","  x  ",
"     ","  x  ",
"xxxxx","  x  ",
"     ","  x  ",
"     ","  x  ",
"Carrier","#80ff80","#408040",
"     ","  x  ",
"  xx ","  x  ",
"xxxxx","  xx ",
"     ","  xx ",
"     ","  x  ",
"Destroyer","#ffff00","#808000",
"     ","     ",
"     ","  x  ",
" xxx ","  x  ",
"     ","  x  ",
"     ","     ",
"Gunboat","#ff8000","#804000",
"     ","     ",
"     ","  x  ",
"  xx ","  x  ",
"     ","     ",
"     ","     ",
"Gunboat","#ff00ff","#800080",
"     ","     ",
"     ","  x  ",
"  xx ","  x  ",
"     ","     ",
"     ","     ",
"");

// x:0-4 y:0-4 s:1-5 r:0-1
function battleShipsGetShipDef(x,y,s,r) {
	if ((x<0) || (x>4) || (y<0) || (y>4)) return 0;
	if (battleShipsShipDef[(s-1)*13 + 3 + r + y*2].charAt(x) == 'x') {
		return 1;
	} else {
		return 0;
	}
}

//  Data format: 
//    visible 0=no, 1=yes
//    type    0=water, x=ship (id)
//    hit     0=miss, 1=hit

function battleShipsGetMapDataVisible(p,x,y) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return 1;
	return battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell];
};
function battleShipsSetMapDataVisible(p,x,y,val) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return;
	battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell]=val;
};

function battleShipsGetMapDataShip(p,x,y) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return 0;
	return battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell + 1];
};
function battleShipsSetMapDataShip(p,x,y,val) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return;
	battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell + 1]=val;
};

function battleShipsGetMapDataHit(p,x,y) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return 0;
	return battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell + 2];
};
function battleShipsSetMapDataHit(p,x,y,val) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return;
	battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell + 2]=val;
};

function battleShipsGetMapDataAI(p,x,y) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return 0;
	return battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell + 3];
};
function battleShipsSetMapDataAI(p,x,y,val) {
	if ((x<0) || (x>=battleShipsMapSizeX) || (y<0) || (y>=battleShipsMapSizeY)) return;
	battleShipsMapData[(p-1)*(battleShipsMapSizeX*battleShipsMapSizeY)*battleShipsMapDataPrCell+(x+y*battleShipsMapSizeX)*battleShipsMapDataPrCell + 3]=val;
};

function battleShipsUpdateMapCell(p,x,y) {
//	sname = "map_"+p+"_"+x+"_"+y;
//	cell = document.getElementsByName(sname).item(0);
	cell = getId("map_"+p+"_"+x+"_"+y);
	if (battleShipsGetMapDataVisible(p,x,y)) {
		if (battleShipsGetMapDataHit(p,x,y)) {
			if (gameOver) {
				cell.style.background = battleShipsShipDef[2 + 13*(Math.round(battleShipsGetMapDataShip(p,x,y))-1)]; // Ships Dark Color
			} else {
				cell.style.background = "#ff0000";	// Hit
			}
		} else {
			if (battleShipsGetMapDataShip(p,x,y)) {
				cell.style.background = "#000000";	// Miss
			} else {
				cell.style.background = "#bbbbff";	// Ship
			}
		}
	} else if ((p==1) && (battleShipsGetMapDataShip(p,x,y)) && (!battleShipsGetMapDataVisible(p,x,y))) {
		cell.style.background = battleShipsShipDef[1 + 13*(Math.round(battleShipsGetMapDataShip(p,x,y))-1)]; // Ships
	} else if (!battleShipsGetMapDataShip(p,x,y) && gameOver) {
		cell.style.background = battleShipsShipDef[1 + 13*(Math.round(battleShipsGetMapDataShip(p,x,y))-1)]; // Ships Dark Color
	} else {
		cell.style.background = "#0000ff";		// Unknown
	}
};

var battleShipsAnimTimerID = 0;
var battleShipsAnimC = 0;

function battleShipsAnimMapCellTick(p,x,y) {
	battleShipsSetMapDataVisible(p,x,y,1-battleShipsGetMapDataVisible(p,x,y))
	
	if ((battleShipsAnimC--) <= 0) {
		clearInterval(battleShipsAnimTimerID);
		battleShipsAnimTimerID = 0;
		var winner = battleShipsWinTest();
		if (winner==1) {
			alert("Game over computer win!");
			if (battleShipsTimerID!=0) clearInterval(battleShipsTimerID);
		} else if (winner==2) {
			alert("Game over you win!");
			if (battleShipsTimerID!=0) clearInterval(battleShipsTimerID);
		}
	}

	battleShipsUpdateMapCell(p,x,y);
}

function battleShipsAnimMapCell(p,x,y) {
	if (battleShipsAnimTimerID==0) {
		battleShipsAnimC = 5;
		battleShipsAnimTimerID = setInterval("battleShipsAnimMapCellTick("+p+","+x+","+y+")", 100);
	}
}

function battleShipsBuildMaps(vertical, cellSize, mapSizeX, mapSizeY) {
	battleShipsMapCellSize = cellSize;
	battleShipsMapSizeX = mapSizeX;
	battleShipsMapSizeY = mapSizeY;

	var x,y;
	var sty = "style='background-color:#808080;border:1px;font-size:xx-small;height:"+battleShipsMapCellSize+"px;width:"+battleShipsMapCellSize+"px;'";
	
	document.write("<table cellpadding='0' cellspacing='1' border='3'><tr><td>");

	document.write("<table cellpadding='0' cellspacing='1'>");
	for (y=0; y<battleShipsMapSizeY; y++) {
		document.write("<tr>");
		for (x=0; x<battleShipsMapSizeX; x++) {
			document.write("<td><center><div id='map_1_"+x+"_"+y+"' "+sty+"></div></center></td>");
		}
		document.write("</tr>");
	}
	document.write("</table>");

	if (vertical) {
		document.write("</td><td>");
	} else {
		document.write("</td></tr><tr><td>");
	}

	document.write("<table cellpadding='0' cellspacing='1'>");
	for (y=0; y<battleShipsMapSizeY; y++) {
		document.write("<tr>");
		for (x=0; x<battleShipsMapSizeX; x++) {
			document.write("<td><center><div id='map_2_"+x+"_"+y+"' "+sty+" onClick='javascript:battleShipsMapClick(2,"+x+","+y+")'></div></center></td>");
		}
		document.write("</tr>");
	}
	document.write("</table>");

	document.write("</td></tr></table>");
}

function battleShipsNewGame() {
	gameOver = false;
	for (var p=1; p<=2; p++) {

		var ships=5;
		for (var j=0; (j<10) && (ships>0); j++)	{
			
			for (var y=0; y<battleShipsMapSizeY; y++) {
				for (var x=0; x<battleShipsMapSizeX; x++) {
					battleShipsSetMapDataVisible(p,x,y,0);
					battleShipsSetMapDataHit(p,x,y,0);
					battleShipsSetMapDataShip(p,x,y,0);
				}
			}

			ships=5;
			for (var i=0; (i<100) && (ships>0); i++) {
				x = Math.round(-0.5 + Math.random()*battleShipsMapSizeX);
				y = Math.round(-0.5 + Math.random()*battleShipsMapSizeY);
				s = ships;// Math.round(-0.5 + Math.random()*2) + 1;
				r = Math.round(Math.random());
				var ok = 1;
				// x:0-4 y:0-4 s:1-2 r:0-1
				for (var xx=0; xx<5; xx++)
					for (var yy=0; yy<5; yy++) {
						if (battleShipsGetShipDef(xx,yy,s,r) && battleShipsGetMapDataShip(p,x+xx,y+yy))
							ok = 0;
						if (battleShipsGetShipDef(xx,yy,s,r) && ((x+xx<0) || (x+xx>=battleShipsMapSizeX) || (y+yy<0) || (y+yy>=battleShipsMapSizeY)))
							ok = 0;
					}
				if (ok==1) {
					for (var xx=0; xx<5; xx++)
						for (var yy=0; yy<5; yy++)
							if (battleShipsGetShipDef(xx,yy,s,r))
								battleShipsSetMapDataShip(p,x+xx,y+yy,ships);
					ships--;
				}
			}		
		}
	}
}

function battleShipsUpdateMaps() {
	for (var p=1; p<=2; p++)
		for (var y=0; y<battleShipsMapSizeY; y++)
			for (var x=0; x<battleShipsMapSizeX; x++)
				battleShipsUpdateMapCell(p,x,y);
}

function battleShipsWinTest() {
	var winner;
	winner = 1;
	for (var p=1; p<=2; p++) {
		for (var y=0; (y<battleShipsMapSizeY) && (winner!=0); y++)
			for (var x=0; (x<battleShipsMapSizeX) && (winner!=0); x++)
				if (battleShipsGetMapDataShip(winner,x,y) && !battleShipsGetMapDataHit(winner,x,y))
					winner = 0;				
		if ((p==1) && (winner==0)) winner = 2;
	}
	if (winner!=0) {
		gameOver = true;
		battleShipsUpdateMaps();
	}
	return winner;
}

function battleShipsShoot(p,x,y) {
	battleShipsSetMapDataVisible(p,x,y,1);
	if (battleShipsGetMapDataShip(p,x,y)) {
		battleShipsSetMapDataHit(p,x,y,1);
	} else {
		battleShipsSetMapDataHit(p,x,y,0);
	}
	battleShipsUpdateMapCell(p,x,y);
}

function battleShipsComputerTurn() {
	if (battleShipsAnimTimerID==0) {
		var x=0;
		var y=0;
		var max = 0;
	
		clearInterval(battleShipsTimerID);
		battleShipsTimerID = 0;

		for (x=0; x<battleShipsMapSizeX; x++)
			for (y=0; y<battleShipsMapSizeY; y++)
				battleShipsSetMapDataAI(1,x,y,(x+y)&1);

		for (var s=1; s<=5; s++) {
			for (var r=0; r<=1; r++)
				for (x=-5; x<battleShipsMapSizeX+5; x++)
					for (y=-5; y<battleShipsMapSizeY+5; y++) {
						var ok = 1;
						for (var xx=0; (xx<5) && (ok!=0); xx++)
							for (var yy=0; (yy<5) && (ok!=0); yy++)
								if (battleShipsGetShipDef(xx,yy,s,r)) {
									if ((x+xx<0) || (x+xx>=battleShipsMapSizeX) || (y+yy<0) || (y+yy>=battleShipsMapSizeY))
										ok = 0; // Outside map
									if (battleShipsGetMapDataHit(1,x+xx,y+yy)) {
										ok = ok * 25; // A hit!
									} else if (battleShipsGetMapDataVisible(1,x+xx,y+yy)) {
										ok = 0; // No hit, and visible = miss
									}
								}
						if (ok>0) {
							for (var xx=0; (xx<5) && (ok!=0); xx++)
								for (var yy=0; (yy<5) && (ok!=0); yy++)
									if (battleShipsGetShipDef(xx,yy,s,r)) {
										battleShipsSetMapDataAI(1,x+xx,y+yy,battleShipsGetMapDataAI(1,x+xx,y+yy) + ok);
										if ((max<battleShipsGetMapDataAI(1,x+xx,y+yy)) && (!battleShipsGetMapDataVisible(1,x+xx,y+yy))) max = battleShipsGetMapDataAI(1,x+xx,y+yy);
									}
						}
					}
		}

		for (var ok=1; ok==1; ) {
			x = Math.round(-0.5 + Math.random()*battleShipsMapSizeX);
			y = Math.round(-0.5 + Math.random()*battleShipsMapSizeY);
			if ((max == battleShipsGetMapDataAI(1,x,y)) && (!battleShipsGetMapDataVisible(1,x,y))) {
				battleShipsShoot(1,x,y);
				battleShipsAnimMapCell(1,x,y);
				ok = 0;
			}
		}
	}
}

function battleShipsMapClick(p,x,y) {
	if ((battleShipsTimerID==0) && (battleShipsAnimTimerID==0)) {
		if (!battleShipsGetMapDataVisible(p,x,y)) {
			battleShipsShoot(p,x,y);
			battleShipsAnimMapCell(p,x,y);
			battleShipsTimerID = setInterval('battleShipsComputerTurn()', 100);
		}
	}
}

