
var xoArray=new Array(0,0,0,0,0,0,0,0,0);//GAME ARRAY
var win=new Array(0,0);//STORES WINNING POSITION ON NEXT MOVE
var gamePlay=new Array();//STORES THE POSITIONS PLAYED BY EVERY PLAYER
var redo=new Array();//STORES UNDO POSITIONS FOR REDO
var turn=1;//SWITCHING GAME PLAYERS
var gameOver=1;//SIGNIFIES IF GAME IS OVER
var block=0;//IF THERE IS A NEED TO BLOCK BY PLAYER
var OK=0;//STORES IF THERE IS TWO WAYS
var moves=0;//COUNTS GAME MOVES
var comp=1;//STARTS COMPUTER AS FIRST PLAYER
var tdref=new Array();//array to hold references to table cells
var tcells=new Array();// array to hold referencrs for onclick activity

function tableMaker(rows,cols){//MAKES THE TABLE
document.write('<table border="1" id="xo" width="300" height="300" align="center">');
var count=0;//USE TO TELL POSITION PLAYED
for (var y=0;y<rows;y++){
document.write('<tr align="center" valign="middle">');
for (i=0;i<cols;i++){
document.write('<td class="normal" name="'+ (count++) +'">&nbsp;-</td>');
//document.write('<td class="normal" name="'+ (count++) +'">' + y , i+ '</td>');
}
document.write('</tr>');
}
document.write('</table>');
}

function smalltableMaker(rows,cols){//MAKES THE TABLE small for the profile page
document.write('<table border="1" id="xoSmall" width="70%" height="70%" align="center">');
var count=0;//USE TO TELL POSITION PLAYED
for (var y=0;y<rows;y++){
document.write('<tr align="center" valign="middle" width="100%" >');
for (i=0;i<cols;i++){
document.write('<td class="normal" name="'+ (count++) +'">-</td>');
//document.write('<td class="normal" name="'+ (count++) +'">' + y , i+ '</td>');
}
document.write('</tr>');
}
document.write('</table>');
}


//tableMaker(3,3);//MAKES THE PLAY AREA

function tableReference(tableid){//MAKES A REFERENCE TO ALL THE TABKE CELLS
// Make sure the browser understands the DOM methods
if (!document.getElementsByTagName) return false;
  if (!document.getElementById) return false;
// Make sure the elements exist
  if (!document.getElementById(tableid)) return false;
var mytable=document.getElementById(tableid);
for (var i=0; i<tcells.length; i++){
tdref[tdref.length]=tcells[i];//mytable.cells[i]; //store references to table cells
if (i>=10){break;}
}//END OF FOR LOOP
//alert(tdref.length); //alerts number of cells in the table
//alert(tdref[8].firstChild.nodeValue);
//alert(tdref[8].getAttribute('name'));
}//END OF FUNCTION
//tableReference();//RUNS FUNCTION

function d_Onclick(tableid){
var tables=document.getElementById(tableid);
 tcells=tables.getElementsByTagName("td");
for (var i=0;i<tcells.length;i++){
tcells[i].onclick=function(){
Swap(this.getAttribute('name'));
}//ONCLICK ATTACHEMNT
}//END OF FOR LOOP
//alert(cells.length);
}//END OF FUNCTION

//d_Onclick();//INITIALISES ATTACHMENT TO ONCLICK FUNCTION


function colorSwap(winner){
var winner=winner;
var computer=document.getElementById('computer').style.backgroundColor;
var human=document.getElementById('yours').style.backgroundColor;
if (computer=='blue' || computer =='' && winner==comp){//computer won
computer='red';
}else{
computer='blue';
}

if (human=='blue' || human=='' && winner!=comp){//THAT MEANS HUMAN WON
human='red';
}else{
human='blue';
}

}//END OF FUNTION


function arrayUpdate(position,turn){//DOES SWAP AND UPDATE
//moves++;//HOW MANY MOVES HAVE BEEN MADE
var values;
xoArray[position]=turn;//UPDATE ARRAY
if(turn==comp){values='O';
tdref[position].style.backgroundColor='red';
}else{values='X';
tdref[position].style.backgroundColor='blue';
}
tdref[position].firstChild.nodeValue=values;//UPDATE DISPLAY
if(checkSum(turn,1)){//IF GAME IS WON
gameOver=false; 
//alert(turn + ' WINNER');
if (turn==comp){//IF COMPUTER WON UPDATE SCORES
var scores=document.getElementById('computer').firstChild.nodeValue;
scores=parseInt(scores);
scores=scores+1;
document.getElementById('computer').firstChild.nodeValue=scores;
//alert('Computer Win');
colorSwap(turn);
}
else{//IF HUMAN WON UPDATE SCORES
var scores=document.getElementById('yours').firstChild.nodeValue;
scores=parseInt(scores);
scores=scores+1;
document.getElementById('yours').firstChild.nodeValue=scores;
//alert('You Win');
colorSwap(turn);
}
}//END OF IF GAME IS WON
if(checkSum(turn,2)){//IF OPPONENT PLANS TO WIN BLOCK
//alert(turn + ' plans to win');
if (turn==1){
block=true;
//block(position);
}
}//OPPONENT BLOCK
}//END OF FUNCTION


function Swap(position){
if (xoArray[position]==0 && gameOver){//IF THE VALUE AT THAT PLACE IS ZERO SWAP
gamePlay[gamePlay.length]=position;//STORING POSITION PLAYS
moves++;//COUNTS HOW MANY MOVES MADE
if (turn==2){
arrayUpdate(position,turn);
turn=1;
//tdref[position].style.backgroundColor='red';
//tdref[position].style.color='white';
//tdref[position].style.fontWeight='bold';
}
else{
arrayUpdate(position,turn);
turn=2;
//tdref[position].style.backgroundColor='blue';
//tdref[position].style.color='white';
//tdref[position].style.fontWeight='bold';
//block=false;
}


if (turn==1 && comp==1){//COMPUTER PLAYING FIRST PLAYER
intelligence1();
turn=2;
}

if (turn==2 && comp!=1){//COMPUTER PLAYERING SECOND PLAYER
intelligence();
turn=1;
}

}//END OF FIRST IF
else if(gameOver){
//alert('NOT EMPTY');
}else {
resets(turn);//alert('GameOVER');
}
}//END OF FUNCTION


function zeroCount(turnto,x,y,z){//CHECKS HOW MANY ZEROS IN A LINE
var count=0;
var turnto=turnto;
if (xoArray[x]==0){++count;winPoint(turnto,x);}
if (xoArray[y]==0){++count;winPoint(turnto,y);}
if (xoArray[z]==0){++count;winPoint(turnto,z);}
return count;
}//END OF FUNCTION

function winPoint(turnto,position){//STORES WINNING POSITIONS FOR 1 AND 2
win[turnto-1]=position;
//alert ('winPointfunction=' + turnto +' is ' + win[turn-1]);
}

function oneWayAttack(turn){//FINDS A POINT FOR ONE WAY ATTACK THAT IF I PLAY, IT WONT CREATE A TWO WAYS FOR OPPONENT
var turnto=turn; var play=false;var stop=0;var store=Array();
if (turn==2){var opp=1;}else{var opp=2;}
for (var i=0;i<9,stop==0;i++){
if(xoArray[i]==0){
xoArray[i]=turnto;
if(checkSum(turnto,2)){
if (turn==2){xoArray[win[1]]=1;}else{xoArray[win[0]]=2;}//BY PLAYING HERE TO THREATEN TO WIN;
if(!twoCount(opp)){//,DOES BLOCKING CREATE TWO WAYS
store[store.length]=i;
}
if (turn==2){xoArray[win[1]]=0;}else{xoArray[win[0]]=0;}//win[1];
//xoArray[win[1]]=0;//RESETTING ARRAY
}
xoArray[i]=0;//RESETING ARRAY
}//END OF EMPTY CELLS
if(i==8){
play=store[Math.floor(Math.random()*store.length)];
stop=1;
}
}//END OF FOR LOOP
return play;
}//END OF FUNCTION

function checkSum(turn,type){//USED TO FIND OUT THE TYPES OF VALUES IN A VALID MOVE. ACTUALLY GAME STATUS INSPECTION
var x=y=z=sum=0; var turnto=turn;
var possibleMoves=new Array('012','345','678','036','147','258','048','246');
for (var i=0;i<possibleMoves.length;i++){
 x=possibleMoves[i].substring(1,0);
 y=possibleMoves[i].substring(2,1);
 z=possibleMoves[i].substring(3,2);
sum=xoArray[x]+xoArray[y]+xoArray[z];
if (sum==(turnto*3) && xoArray[x]!=0 && xoArray[y]!=0 && xoArray[z]!=0 && type==1){//FOR IF WON
//alert(x+y+z);
return true;
}//END OF IF LOOP

if(sum==(turnto*2) && (zeroCount(turnto,x,y,z)==1) && type==2){//FOR ATTEMPT TO WIN
return true;
}//END OF IF LOOP

}//END OF FOOR LOOP
return false;
}//END OF FUNCTION

function validPoint(position){//LOOKS FOR A VALID EMPTY POINT
var positions=position;
if(xoArray[positions]==0){
return true;//NOT AN EMPTY POSITION
}
return false;
}//END OF FUNCTION

function advice(turn){//GIVES ADVICE ON WHERE TO PLAY
if (turn==1 && validPoint(win[1])){
alert(turn+ ' Play at ' + win[1]);
}if(turn==2 && validPoint(win[0])){
alert(turn + ' Play at ' + win[0]);
}
}

function getValidation(){//SENDING BACK EMPTY CELLS IF ANY
//alert('getting valid point cos win[0]=' + win[0] + ' win[1]='+ win[1]);
for (var i=0;i<xoArray.length;i++){
if (xoArray[i]==0){
//alert('return ' + i);
return i;//RETURNING POINT FOR ANALYSIS IF IT IS A GOOD PLAY
}
}//
gameOver=0;
return 10;
}

function twoCount(turnto){//FINDING TWO WAYS MOVE FOR A ANY PLAYER
var turnto=turnto;
var two=sum=0;
var possibleMoves=new Array('012','345','678','036','147','258','048','246');
for (var i=0;i<possibleMoves.length;i++){
x=possibleMoves[i].substring(1,0);
y=possibleMoves[i].substring(2,1);
z=possibleMoves[i].substring(3,2);
sum=xoArray[x]+xoArray[y]+xoArray[z];
//alert(x+y+z);
if (sum==(turnto*2) && zeroCount(turnto,x,y,z)==1){
two++;
//alert('one');
}//END OF IF LOOP
}//END OF FOR LOOP
if (two==2){
//alert('FOUND');
return true;
}
return false;
}//END OF FUNCTION


function intelligence(){//AI FOR WHEN COMP PLAYS SECOND PLAYER
var point=0;
if (validPoint(win[1]) && win[1] && moves>3){//CAN I WIN, THEN WIN
//alert ('win[1] is ' + win[1]);
point=win[1];
win[1]=0;//Swap(win[1]); 
}else if(validPoint(win[0]) && block){//SHOULD I BLOCK THEN BLOCK
//alert ('win[0] is ' + win[0]);
point=win[0];//	BLOCK AT THIS POSITION
block=false;
win[0]=0;
}else if(moves==1){//END OF VALID POINT, GET A VALID OPENING POINT
point=openMove(gamePlay[0]);//getValidation();
}else if(moves<7){//GET A POSITION THAT IF I PLAY, I WILL THREATEN TO WIN AND NOT CREATE TWO WAYS FOR OPP IF BLOCKED
point=oneWayAttack(2);
//alert('oneway');
}else {//ELSE FILL UP BLANK SPACES IF ANY
point=getValidation();
//alert('getValid');

}
if (point>10){//IF THERE ISNT ANY, SIGNIFY DRAW
//alert('DRAW');

}else{
Swap(point);
}
}//END OF FUNCTION

function redoing(turn){
moves++;
if(moves<=9 && redo[redo.length-1]!=null){
alert(turn);
var text;
if(turn==2){
turn=1;
tdref[redo[redo.length-1]].style.backgroundColor='blue';
text='0';
}else if(turn==1){
turn=2;text='X';
tdref[redo[redo.length-1]].style.backgroundColor='red';
}
//alert(redo[redo.length-1]);
gamePlay[gamePlay.length]=redo[redo.length-1];//RESTORING GAME PLAY ORDER
//tdref[redo[redo.length-1]].style.backgroundColor='red';
tdref[redo[redo.length-1]].firstChild.nodeValue=text;
redo=redo.slice(0,redo.length-1);
alert(turn);
}
}//END OF FUNCTION

function undo(turn){
moves--;
if(moves>1){
redo[redo.length]=gamePlay[gamePlay.length-1];//STORING LAST POSITION PLAYED FOR REDO
tdref[gamePlay[gamePlay.length-1]].firstChild.nodeValue=" ";
tdref[gamePlay[gamePlay.length-1]].style.backgroundColor='#ffffff';
gamePlay=gamePlay.slice(0,gamePlay.length-1);//REDUCING ARRAY LENGTH BY ONE
xoArray[gamePlay[gamePlay.length-1]]=0;//RESETTING ARRAY
if(turn==2){turn=1;}else{turn=2;}
}
}//END OF FUNCTION

function resets(computer){//RESETS THE ARRAY AND TABLE TO START A NEW GAME
xoArray=Array(0,0,0,0,0,0,0,0,0);//RESETING ARRAY FOR A NEW GAME
win=Array(0,0);redo=Array();
gamePlay=Array();moves=0;
turn=1;gameOver=1;block=0;OK=0;comp=computer;
//END OF RESETING ARRAY
for(var i=0;i<=8;i++){
tdref[i].firstChild.nodeValue="-"//UPDATE DISPLAY
tdref[i].style.className='normal';
tdref[i].style.backgroundColor='#ffffff';
}//END OF FOR LOOP
if(comp==1){//COMPUTER FIGHTS FIRST
//var point=
intelligence1();
turn=2;
}
}//END OF FUNCTION

function openMove(firstmove){//WHEN PLAYING SECOND PLAYER RETURNS BEST OPEN POSITION BASED ON OPP FIRST MOVE
var firstMove=firstmove;//gamePlay[0];
var rand=Math.floor(Math.random()*6);
return openingArray[firstMove][rand];
}//END OF FUNCTION

function whereISWin(turn){//FINDING A PLACE WHERE TO PLAY TO WIN THE GAME 
var turnto=turn;var play=10;
//var dxoArray=new Array();
//dxoArray=xoArray;
for (var i=0;i<9;i++){
if(xoArray[i]==0){
xoArray[i]=turnto;
if(checkSum(turnto,1)){//WINING POSITION
//play=i;
xoArray[i]=0;//RESETING ARRAY
return i; 
//alert('play');
}//END OF CHECKSUM
xoArray[i]=0;//RESETING ARRAY
}//END OF IF LOOP
}//END OF FOR LOOP
return play;
}//END OF FUNCTION

function intelligence1(){//WHEN COMP IS PLAYING FIRST PLAYER MODE
//LOGIC NEEDS TO BE FURTHER ARRANGED AND IMPROVED UPON TO BE UNDEFEATABLE
var points=0;
if (moves==0){//ON FIRST MOVE, COMP PLAYS ANYWHERE AT RANDOM
points=Math.floor(Math.random()*8);
}

else if(moves==2){//ON SECOND MOVE, COMP CHECKS IF HE CAN MAKE TWO WAYS
points=attackPlay(turn);
if(points!=10){//IF THERE IS ONE FOR THE USER PLAYED A BAD OPEN MOVE SIGNIFY BY MAKING 'OK' TRUE
//alert('two ways');
OK=true;//THERE ARE TWO WAYS
}
else{//IF THERE ISNT AND THE USER OPEN MOVE IS GOOD CHECK IF THERE IS A PLACE WHERE COMP CAN PLAY THAT WONT CAUSE TWO WAYS
//USING ONEWAY ATTACK FUNCTION
//alert('two ways not found');
points=oneWayAttack(1);//whereISWin(1);//oneWays(1);
}
}else if(moves>2 && validPoint(win[0])){//WIN IF THERE IS AN OPPORTUNITY TO DO SO
//FURTHER IMPROVEMENT CAN BE DONE IF WIN[0] IS NOT DISTURBED DURING ALL THE CHECKS OR A STORE IS MADE FOR STORING THE TWO WAYS
//POSITION THERE WINNING POINTS
//alert('WIN ==' + win[0]);
points=win[0];
}else if(moves>2 && OK){//IF THE USER BLOCKS AND IT HAS BEEN SIGNIFIED THERE IS A WINNING POINT, CALL FUNCTION TO FIND THE WINING
//POSITION THAT IF PLAYED WILL FIND TWO WAYS
//alert('finding two ways');
points=findTwoWays(1);
if(points==10){//IF THERE ISN'T, FUNCTION findTwoWays RETURNS 10
//alert('whereiswin3');
points=whereISWin(1);//findTwoWays(1);
}
}
else if (moves>2 && validPoint(win[1])){//DEFEND and BLOCK IF THERE IS A THREAT OF LOSING GAME
//alert('defend and block');
points=win[1];//getValidation();
}
else if(OK){//IF THERE ISNT A THREAT OF LOSING, FIND THE WINNING POINT TO END GAME WITH whereISWIN FUNCTION
//alert('whereiswin2');
points=whereISWin(1);//findTwoWays(1);
}
else{//JUST FILL VALID EMPTY POSITIONS
//alert('getValidation');
points=getValidation();
}
Swap(points);//SEND FINAL DECISION TO FUNCTION
}//END OF FUNCTION

function findTwoWays(turnto){//GIVEN TURN, IT CHECKS IF THERE IS A PLACE THAT IF I PLAY, THERE WILL BE TWO WAYS
//NEEDS TO BE FURTHER IMPROVED FOR IT RETURNS 'PLAY==3' SOMETIMES INSTEAD OF TEN WHEN CHECKING FOR TWO WAYS THE SECOND TIME
//IF THIS IS CURED, 1 PLAYER WILL BE UN DEFEATABLE
//var dxoArray=new Array();
var playing=10;
//xoArray=xoArray;
for(var i=0;i<9;i++){
if(xoArray[i]==0){
xoArray[i]=turnto;
if(twoCount(turnto)){//CALLS FUNCTION TO CHECK IF THERE IS TWO WAYS
//play=i;
xoArray[i]=0;//RESETING ARRAY
//alert('PLAY ==' + i);
return i;
}
xoArray[i]=0;//RESETING ARRAY
}//END OF EMPTY SET
}//END OF FOR LOOP
//alert('PLAY --' + playing);
return playing;
}//END OF FUNCTION

function attackPlay(turn){//FINDING TWO WAYS
var y=0;
var play=10;
var dxoArray=new Array();
dxoArray=xoArray;var block=0;
var store=new Array();
for (var i=0;i<=8,y==0;i++){
//alert(i)
if(xoArray[i]==0){//IF A VALID POINT
xoArray[i]=turn;// alert('I ' +i);
   if(checkSum(turn,2)){//IF I PLAN TO WIN, BLOCK
      //alert(turn + ' plans to win therefore block at '+ win[0]);
      var wining=win[0];
       // if (turn==2){var oppblock=1;}else{var oppblock=2;}
         xoArray[wining]=oppblock=2;
              if(checkSum(oppblock,2)){//IF THE BLOCK WILL CAUSE A WIN IN NEXT MOVE BLOCK
         block=win[1];
    //  alert('2 plans to win therefore play at ' + win[1]);
        xoArray[block]=turn;
     //alert ('block');
         if(twoCount(turn)){
         
           play=store[store.length]=i;//GAME ALREADY IN TWO WAYS MODE COS OF BLOCK
             //y=1;
             		
            //    alert ('GAME ALREADY IN MODE at ' + i);
              }
             
          xoArray[block]=0;//RESETTING ARRAY
       }//END OF IF OPP PLANS TO WIN
       else{
                 //alert ('GAME not ALREADY IN MODE');
                  for (var t=0;t<9;t++){
                  if(xoArray[t]==0){
                  xoArray[t]=turn;
                  if(twoCount(turn)){
                   //alert ('GAME 2ways IN MODE at ' + t);
                play= store[store.length]=t;
                  }
                  xoArray[t]=0;//RESETTING ARRAY
                  }//END OF IF EMPTY
                  }//END OF FOR LOOP

               }
xoArray[wining]=0;//RESETTING ARRAY
}//END OF CHECK IF ABOUT TO WIN AND PLAN TO WIN
xoArray[i]=0;//RESETTING ARRAY
}//END OF IF LOOP VALID POINT
if(i==8){y=1;}
}//END OF FOR LOOP
if(store.length!=0){
play=store[Math.floor(Math.random()*store.length)];
//alert('PLAY' + play);
}
return play;
}//END OF FUNCTION



var openingArray=new Array();
openingArray[0]=new Array();
openingArray[1]=new Array();
openingArray[2]=new Array();
openingArray[3]=new Array();
openingArray[4]=new Array();
openingArray[5]=new Array();
openingArray[6]=new Array();
openingArray[7]=new Array();
openingArray[8]=new Array();

openingArray[0][0]=4;
openingArray[0][1]=4;
openingArray[0][2]=4;
openingArray[0][3]=4;
openingArray[0][4]=5;
openingArray[0][5]=8;
openingArray[0][6]=7;

openingArray[1][0]=2;
openingArray[1][1]=4;
openingArray[1][2]=7;
openingArray[1][3]=7;
openingArray[1][4]=5;
openingArray[1][5]=3;
openingArray[1][6]=8;

openingArray[2][0]=4;
openingArray[2][1]=4;
openingArray[2][2]=4;
openingArray[2][3]=4;
openingArray[2][4]=7;
openingArray[2][5]=6;
openingArray[2][6]=3;

openingArray[3][0]=0;
openingArray[3][1]=4;
openingArray[3][2]=5;
openingArray[3][3]=6;
openingArray[3][4]=2;
openingArray[3][5]=8;
openingArray[3][6]=1;

openingArray[4][0]=0;
openingArray[4][1]=2;
openingArray[4][2]=6;
openingArray[4][3]=8;
openingArray[4][4]=7;
openingArray[4][5]=5;
openingArray[4][6]=1;

openingArray[5][0]=2;
openingArray[5][1]=3;
openingArray[5][2]=4;
openingArray[5][3]=8;
openingArray[5][4]=6;
openingArray[5][5]=1;
openingArray[5][6]=7;

openingArray[6][0]=4;
openingArray[6][1]=4;
openingArray[6][2]=4;
openingArray[6][3]=4;
openingArray[6][4]=3;
openingArray[6][5]=2;
openingArray[6][6]=7;

openingArray[7][0]=1;
openingArray[7][1]=4;
openingArray[7][2]=6;
openingArray[7][3]=8;
openingArray[7][4]=5;
openingArray[7][5]=7;
openingArray[7][6]=3;

openingArray[8][0]=4;
openingArray[8][1]=4;
openingArray[8][2]=4;
openingArray[8][3]=4;
openingArray[8][4]=1;
openingArray[8][5]=5;
openingArray[8][6]=3;

function start(){

if (turn==1 && comp==1){//STARTS THE GAME AUTOMATICALLY BY SETTING COMPUTER TO FIRST PLAYER
intelligence1();
turn=2;
}

}

function loadfunc(){//AN ONLOAD FUNCTION
d_Onclick('xoSmall');
tableReference('xoSmall');//RUNS FUNCTION
};
