// MineField v1.0
// Author: Brian Gosselin
// Site: http://scriptasylum.com
// Copyright 2004

var pL=false, gO=true;
var mineField=null;
var mA, mF;
var seconds=0, tID=0, totalClicked=0;
var mouseB='';
var rows=10, cols=10, mines=10;
document.forms["f"].reset();


//SETS ROWS, COLS, AND MINES
function setParameters(){
var d=document.forms["f"];
if( (d.r.selectedIndex*5+5==rows) && (d.c.selectedIndex*5+5==cols) && (d.m.selectedIndex*15+10==mines) )resetMineField();
else{
mineField.innerHTML='Please wait while game is built...';
setTimeout('subParams()',100);
}}


//USED WITH setParameters() TO DELAY LONG ENOUGH TO DISPLAY MESSAGE IN MINEFIELD AREA
function subParams(){
var d=document.forms["f"];
rows=d.r.selectedIndex*5+5;
cols=d.c.selectedIndex*5+5;
mines=d.m.selectedIndex*15+10;
buildMineField();
}


//FUNCTION TO TEST FOR AND START TIMER
function testTimer(){
if(seconds==-1){
seconds=0;
tID=setInterval('timer()',1000);
}}


//OFFERS A HINT BY SHOWING A RANDOM NON-MINE SQUARE
function showSquare(){
if(!gO && pL){
testTimer();
var tr,tc,ta;
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
ta=mA[r][c];
if(!ta.hasMine && !ta.clicked && !ta.flagged && !gO && pL){
ta.clicked=true;
document.images["img"+ta.idnum].src="number"+ta.mineCount+".gif";
findMines(ta.idnum);
r=rows-1;
c=cols-1;
}}}}}


//OFFERS A HINT BY SHOWING A RANDOM MINE
function showMine(){
if(!gO && pL){
testTimer();
var tr,tc,ta;
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
ta=mA[r][c];
if(ta.hasMine && !ta.clicked && !ta.flagged){
mF+=1;
document.images["img"+ta.idnum].src="flag.gif";
ta.flagged=true;
setMineCounter(mines-mF);
r=rows-1;
c=cols-1;
}}}}}


//PAUSE
function pauseGame(){
gO=!gO;
}

//SUB-FUNCTION TO FIND ELEMENT REFERENCE
function findID(n){
return (document.all)?document.all[n]:document.getElementById(n);
}


//COUNTDOWN TIMER DISPLAYED VIA IMAGES.
function timer(){
if(!gO){
seconds++;
var n=Math.max(Math.min(999,seconds),0)+'';
while(n.length<3)n="0"+n;
n=n.split("");
document.images["tmr_1"].src="lcd"+n[0]+".gif";
document.images["tmr_2"].src="lcd"+n[1]+".gif";
document.images["tmr_3"].src="lcd"+n[2]+".gif";
}}


//SETS THE MINECOUNTER LCD READOUT VIA IMAGES.
function setMineCounter(n){
if(n>=0){
n=Math.min(n,999);
n+='';
while(n.length<3)n="0"+n;
}else{
n=Math.min(Math.abs(n),99);
n="n"+n;
while(n.length<3)n="b"+n;
}
n=n.split("");
document.images["cnt_1"].src="lcd"+n[0]+".gif";
document.images["cnt_2"].src="lcd"+n[1]+".gif";
document.images["cnt_3"].src="lcd"+n[2]+".gif";
}


//PARSE OUT THE ROW & COL NUMBER FROM A STRING AND RETURN AN ARRAY OF [R,C].
function getRC(s){
var ta=new Array();
ta[0]=parseInt(s.substring(1,s.indexOf('c')));
ta[1]=parseInt(s.substring(s.indexOf('c')+1,s.length));
return ta;
}


//GIVES ERROR MESSAGE IF ROWS, COLS, AND/OR MINE COUNT IS SMALLER THAN REQUIRED.
function testMinesRowsCols(){
var t='';
if( rows*cols<25 || mines>(rows*cols)-10 )t='One or more of the grid or<br>mine count settings are<br>out of range.<br><br>Pick valid settings and<br>try again.'
return t;
}


//USED TO CHEAT :) TO FIND STATS FOR A SPECIFIC ROW/COL
function showStats(r,c){
var t='Total Clicked: '+totalClicked+'\n';
t+='Row: '+r+'\n';
t+='Col: '+c+'\n';
t+='Has Mine: '+((mA[r][c].hasMine)?'YES':'NO')+'\n';
t+='Mines Around: '+mA[r][c].mineCount+'\n';
t+='Clicked: '+((mA[r][c].clicked)?'YES':'NO')+'\n';
t+='flagged: '+((mA[r][c].flagged)?'YES':'NO')+'\n';
alert(t);
}


//USED TO CHEAT :) SHOWS WHOLE GRID WITH MINE PLACEMENT
function showGrid(){
var t='';
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
t+=(mA[r][c].hasMine)?'X ':'o ';
}
t+='\n';
}
alert(t)
}


//CLEAR ALL SQUARES AROUND CLICKED ONE IF THERE ARE NO ADJACENT BOMBS
function clearSquares(r,c){
if(mA[r][c].mineCount==0 && !gO){
var ta;
if(r>0 && c>0){
ta=mA[r-1][c-1];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r-1)+"c"+(c-1)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+(r-1)+','+(c-1)+')',20);
}}
if(r>0){
ta=mA[r-1][c];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r-1)+"c"+(c)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+(r-1)+','+c+')',20);
}}
if(r>0 && c<cols-1){
ta=mA[r-1][c+1];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r-1)+"c"+(c+1)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+(r-1)+','+(c+1)+')',20);
}}
if(c>0){
ta=mA[r][c-1];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r)+"c"+(c-1)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+r+','+(c-1)+')',20);
}}
if(c<cols-1){
ta=mA[r][c+1];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r)+"c"+(c+1)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+r+','+(c+1)+')',20);
}}
if(r<rows-1 && c>0){
ta=mA[r+1][c-1];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r+1)+"c"+(c-1)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+(r+1)+','+(c-1)+')',20);
}}
if(r<rows-1){
ta=mA[r+1][c];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r+1)+"c"+(c)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+(r+1)+','+c+')',20);
}}
if(r<rows-1 && c<cols-1){
ta=mA[r+1][c+1];
if(!ta.clicked && !ta.hasMine && !ta.flagged){
ta.clicked=true;
totalClicked++;
document.images["imgr"+(r+1)+"c"+(c+1)].src="number"+ta.mineCount+".gif";
setTimeout('clearSquares('+(r+1)+','+(c+1)+')',20);
}}testWin();
}}


//FIND NUMBER OF MINES AROUND THE CLICKED SQUARE.
function findMines(t){
var r=getRC(t)[0];
var c=getRC(t)[1];
mA[r][c].clicked=true;
totalClicked++;
if(mA[r][c].mineCount==0)clearSquares(r,c);
else document.images["img"+t].src="number"+mA[r][c].mineCount+".gif";
testWin();
}


//TEST FOR WIN
function testWin(){
if(rows*cols-mines == totalClicked){
clearInterval(tID);
document.images["smilie"].src="smile5.gif";
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
if(mA[r][c].hasMine)document.images["imgr"+r+"c"+c].src="flag.gif";
}}
gO=true;
setMineCounter(0);
alert('***  You Won!  ***');
}}


//HANDLE MOUSEDOWN EVENT
function toggleFlag(e){
testTimer();
if(!gO){
if(!e)var e=window.event;
if(e.which)mouseB=(e.which<=1)?"L":"R";
else if(e.button)mouseB=(e.button==1)?"L":"R";
if(mouseB=="R"){
if(!this.clicked){
if(this.flagged){
mF-=1;
document.images["img"+this.idnum].src="square.gif";
}else{
mF+=1;
document.images["img"+this.idnum].src="flag.gif";
}
this.flagged=!this.flagged;
setMineCounter(mines-mF);
}}else{
if(!this.clicked && !this.flagged){
document.images["smilie"].src="smile3.gif";
document.images["img"+this.idnum].src="number0.gif";
}}}}


//HANDLE MOUSEUP EVENT
function checkSquareStatus(){
if(!gO){
var r=getRC(this.idnum)[0];
var c=getRC(this.idnum)[1];
//if(this.clicked)document.images["imgr"+r+"c"+c].src="number0.gif";
if(this.clicked)document.images["imgr"+r+"c"+c].src="number"+mA[r][c].mineCount+".gif"
document.images["smilie"].src="smile1.gif";
if(mouseB!="R" && !this.clicked && !this.flagged){
if(this.hasMine){
document.images["img"+this.idnum].src="mine3.gif";
this.clicked=true;
clearInterval(tID);
document.images["smilie"].src="smile4.gif";
gO=true;
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
if(mA[r][c].hasMine && !mA[r][c].clicked)document.images["imgr"+r+"c"+c].src="mine1.gif";
if(!mA[r][c].hasMine && mA[r][c].flagged)document.images["imgr"+r+"c"+c].src="mine2.gif";
}}
return false;
}else findMines(this.idnum);
}}}


//BUILD THE GAMEBOARD AND INITIALIZE
function buildMineField(){
var t=testMinesRowsCols();
if(t!='')mineField.innerHTML=t;
else{
t+='<table cellpadding=0 cellspacing=0 border=0 width="10" class="mineTable">';
for(r=0;r<rows;r++){
t+='<tr>';
for(c=0;c<cols;c++)t+='<td><span id="r'+r+'c'+c+'"><img name="imgr'+r+'c'+c+'" src="square.gif"></span></td>';
t+='</tr>';
}
t+='</table>';
mineField.innerHTML=t;
mA=new Array();
for(r=0;r<rows;r++){
mA[r]=new Array();
for(c=0;c<cols;c++){
mA[r][c]=findID('r'+r+'c'+c);
mA[r][c].idnum='r'+r+'c'+c;
mA[r][c].onmouseover=function(){
if(!this.clicked && !this.flagged && !gO)document.images['img'+this.idnum].src="square.gif";
}
mA[r][c].onmouseout=function(){
if(!this.clicked && !this.flagged && !gO)document.images['img'+this.idnum].src="square.gif";
if(this.clicked && !this.flagged && !gO)document.images['img'+this.idnum].src="number"+this.mineCount+".gif";
}
mA[r][c].onmousedown=toggleFlag;
mA[r][c].onmouseup=checkSquareStatus;
mA[r][c].oncontextmenu=function(){return false;}
mA[r][c].onmouseout=function(){
if(!gO)document.images["smilie"].src="smile1.gif";
}}}
setParameters();
resetMineField();
}}


// RELOAD THE GAME
function resetMineField(){
var t=testMinesRowsCols();
if(t!='')mineField.innerHTML=t;
else{
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
document.images["imgr"+r+"c"+c].src="square.gif";
mA[r][c].clicked=false;
mA[r][c].flagged=false;
mA[r][c].hasMine=false;
mA[r][c].mineCount=0;
}}
var tr,tc;
for(m=1;m<=mines;m++){
tr=Math.floor(Math.random()*rows);
tc=Math.floor(Math.random()*cols);
if(!mA[tr][tc].hasMine)mA[tr][tc].hasMine=true;
else m-=1;
}
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
var ta=mA[r][c];
if(r>0 && c>0)if(mA[r-1][c-1].hasMine)ta.mineCount++;
if(r>0)if(mA[r-1][c].hasMine)ta.mineCount++;
if(r>0 && c<cols-1)if(mA[r-1][c+1].hasMine)ta.mineCount++;
if(c>0)if(mA[r][c-1].hasMine)ta.mineCount++;
if(c<cols-1)if(mA[r][c+1].hasMine)ta.mineCount++;
if(r<rows-1 && c>0)if(mA[r+1][c-1].hasMine)ta.mineCount++;
if(r<rows-1)if(mA[r+1][c].hasMine)ta.mineCount++;
if(r<rows-1 && c<cols-1)if(mA[r+1][c+1].hasMine)ta.mineCount++;
}}
document.images["smilie"].src='smile1.gif';
totalClicked=0;
gO=false;
pL=true;
mF=0;
clearInterval(tID);
seconds=(-2);
timer();
setMineCounter(mines);
}}


//IF NS4, DISPLAY MESSAGE, OTHERWISE INITIATE GAME.
if(document.layers)alert('This game does not work in Netscape4.x.\n\nLooks like it\'s time to upgrade! :)');
else{
window.onload=function(){
mineField=findID('minefield');
findID("cont1").style.visibility="visible";
findID("cont2").style.visibility="visible";
findID("cont3").style.visibility="visible";
findID("cont4").style.visibility="visible";
buildMineField();
}}
