var imageext=".gif";
var maxstones=calculatesigma(1,maximages);

//define field 
 
var fieldarray = new Array(boardsizex);
for (x=0;x<boardsizex;x++) 	{
  fieldarray[x] = new Array(boardsizey);
 }
var stack = new Array(maxstones);
var stackheight=maxstones;
var endpointer= new Array (maxendpoints) ;
for (x=0;x<maxendpoints;x++) 	{
  endpointer[x] = new Object();
 }

//set next player to 0 for no gameplay
var currentplayer=0;
var playerscores = new Array(maxplayer+1);
var score=0
for (n=1;n<=maxplayer;n++)  playerscores[n] = 0;

var inputbufferstone=0
var inputbufferstoneside=0
var has_to_restart=false;

//define field of stones from 1-28 and fill it 
var field = new Array(maxstones);
var stones = new Array();
for (n=0;n<=maxstones;n++)  stones[n] = new Object();
var piece=0;
for (n=0;n<maximages;n++) 
 { 
 for (m=n;m<maximages;m++) 
  {
  piece++;
  stones[piece].left =n;
  stones[piece].right =m;
  stones[piece].pointvalue=m+n;//holds points number
  
  if(m==n) stones[piece].pointvalue=stones[piece].pointvalue+20;
  }
 }


  stones[0].left =0;
  stones[0].right =0;
  stones[0].pointvalue=100;//is set to hundre so that it is sorted to the right.
  

//to hold distribute stones for each players
var playerhold = new Array()
for (n=1;n<=maxplayer;n++) 
 {
 playerhold[n] = new Array()
 for (m=0;m<maxholding;m++) 
  {
  playerhold[n][m] =0;//correct value is inserted in initgam
  }
 }

function initgame()
{
if(!has_to_restart)return;
clearfield()
inputbufferstone=0;
for (n=0;n<=maxplayer;n++) currentmaxinventorypos[n]=initialholding; 

//initialize stack 
for (n=1;n<=maxstones;n++) stack[n]=n;

nostartfound=true;
facecount=maximages;

while (nostartfound ){
//shuffling it
for (n=1;n<=maxstones;n++)
	{
	tmps=randomise(maxstones);
	tmpt=randomise(maxstones);
	tmpstore=stack[tmps];
	stack[tmps]=stack[tmpt];
	stack[tmpt]=tmpstore;
	}
stackheight=maxstones;

//dealing the pieces
for (n=1;n<=maxplayer;n++) 
 {
 for (m=0;m<initialholding;m++) 
  {
  playerhold[n][m] =stack[stackheight];
  stackheight--;  
  }
 }

//handingout pieces done
sortplayer();

//search for startpiece
facecount=maximages;
while (nostartfound && facecount>=0) {
for(n=1;n<=maxplayer;n++)
 { 
 for(m=0;m<initialholding;m++)
  if (stones[playerhold[n][m]].left==facecount && stones[playerhold[n][m]].right==facecount) 
	{
	currentstoneid=playerhold[n][m];
	playerhold[n][m]=0;//first stone removed out of playerhold
	pickstone=m;
	currentplayer=n;//first player who had to place the first piece
	nostartfound=false;
	}
 }
 if (nostartfound) facecount--;
}
} ; //if nothing found  nostartfound is true then it is restarted with reshuffling

puthalfstone(stones[currentstoneid].left,startx,starty);
puthalfstone(stones[currentstoneid].right,startx+1,starty);

//set first endpoints
setendpoint(startx,starty,stones[currentstoneid].left,initialconnectorcount,-1,0); 
setendpoint(startx+1,starty,stones[currentstoneid].right,initialconnectorcount,1,0); 
showhuman();
has_to_restart=false;
alerting(" ");
if (nodrawgame) stackheight=0;
 nextplayer();

} ;//end of init game

function setendpoint(x,y,val,cc,dx,dy) {
//find an empty slot in endpointer array
for (n=maxendpoints-1;n>=0;n--) if (endpointer[n].value==-1) foundslot=n;
endpointer[foundslot].x= x; 
endpointer[foundslot].y= y; 
endpointer[foundslot].value=val;
endpointer[foundslot].connectorcount=cc; 
endpointer[foundslot].directionx=dx;
endpointer[foundslot].directiony=dy;
}


function dealstone(ply) {
	if (stackheight<1) return;
	dspos=0;
	while(playerhold[ply][dspos]>0 && dspos<maxstones) dspos++;
	if (dspos<maxstones) {
		playerhold[ply][dspos] =stack[stackheight];
		stackheight--;  
		if ((currentmaxinventorypos[ply])<=dspos) 
			currentmaxinventorypos[ply]++;
	}
sort_only_player(ply); 

}


function randomise(maxim)
{
//returns an integer between 1 and maxim.
tmp=Math.floor(Math.random()*maxim +1);
if (tmp>maxim) tmp=maxim;
return tmp;
}

function calculatesigma(startcs,endcs)
{
	var result=0;
	var n;
	if (startcs>endcs) { n= endcs; endcs=startcs;startcs=n; }
	for (n=startcs;n<=endcs;n++) result+=n;
	return result;
}

function setinput(x,y) { inputbufferstone=x; inputbufferstoneside=y; }

function spaceset() {
	this.available=false;
	this.midx=-1;
	this.midy=-1;
	this.endx=-1;
	this.endy=-1;
}

function nextplayer()
{
var foundspace= new spaceset();
showhuman();
if (has_to_restart) return;
currentplayer++
if (currentplayer>maxplayer) currentplayer=1;
n=currentplayer

if (currentplayer==steeringplayer)
 {
 // player is human check for input.
 if (inputbufferstone==10) 
	{ 
	//pass 
	inputbufferstone=0; 
	dealstone(currentplayer)
	checkmoveleft();
	//setTimeout("nextplayer()",10); 
	nextplayer();
	return; 
	} 
 if (inputbufferstone==0)
	{
	// if no input wait another second before calling next player again
	currentplayer--;
	//setTimeout("nextplayer()",10);
	return;
	}
 	else	

	{
        // if input - read input 
	st=playerhold[currentplayer][inputbufferstone-1+inventorypos]
	if (st==0) { currentplayer--; //setTimeout("nextplayer()",10);
		return; }
		
	if (inputbufferstoneside==1) {
		stv1=stones[st].left;	
		stv2=stones[st].right;
	} else {
		stv2=stones[st].left;	
		stv1=stones[st].right;
	}
	
	nothingfound=true;
	for (nm=0;nm<maxendpoints;nm++) {
	
	   //if matching to an endpointer 
	   
	   if ( endpointer[nm].connectorcount>0 && endpointer[nm].value==stv1 ) {
	 	   foundspace=findspacearoundendpoint(nm);
		   if (foundspace.available) {
	 		midx=foundspace.midx;endx=foundspace.endx;
	 		midy=foundspace.midy;endy=foundspace.endy
		 	//if yes show it in the field change mit puthalfstines
			storenm=nm;
			
		 	nothingfound=false;
		 	
	 		
	 	   }
 	    }
	}
	 
	 if( nothingfound ) {  
	 	currentplayer--
	    	// if input read- empty buffer 
	    	inputbufferstone=0
	    	//setTimeout("nextplayer()",10);
	     	return;
	 }

	//set found stones
		 	puthalfstone(stv1,midx,midy)
		 	puthalfstone(stv2,endx,endy)
		 	//change pointer  
		 	cc=standardconnectorcount;
		 	if (stv1==stv2) cc= doublefaceconnectorcount;
		 	setendpoint(endx,endy,stv2,cc,endx-midx,endy-midy); 
		 	endpointer[storenm].connectorcount =endpointer[storenm].connectorcount-1;

	//remove stone from player 
	playerhold[currentplayer][inputbufferstone-1+inventorypos]=0;
	// if input read- empty buffer 
	inputbufferstone=0;
	showhuman();
	 if(!gameover(currentplayer)) {
	 	//#setTimeout("nextplayer()",10);
	 	alerting("cards left on stack"+stackheight);
		nextplayer();
		}
	return;
	} 
 }
 else
 {
 //player is machine 
 //take first right in own stone array and call next 
 curendpoint=-1;
 firststone=-1
 for (m= maxholding-1;m>=0;m--)
  {
  st=playerhold[currentplayer][m]
  if(!(st==0)  && firststone==-1)
	{
	    for (nm=0;nm<maxendpoints;nm++) {
		foundspace=findspacearoundendpoint(nm);
		if (foundspace.available) {
	 		if (stones[st].left==endpointer[nm].value) { 
	 		 	firststone=m;swapflag=false;curendpoint=nm;  
				midx=foundspace.midx;endx=foundspace.endx;
	 		 	midy=foundspace.midy;endy=foundspace.endy;
	 		 }
			if (stones[st].right==endpointer[nm].value) { 
				firststone=m;swapflag=true; curendpoint=nm; 
				midx=foundspace.midx;endx=foundspace.endx;
	 		 	midy=foundspace.midy;endy=foundspace.endy;
			}
		}
	    }
	}
  }
 if (firststone==-1) {
	 //#setTimeout("nextplayer()",5);
	//pass
	dealstone(currentplayer);
	nextplayer();
	 return;
	 }
 //line above passed.
 m=firststone;
 stv1=stones[playerhold[currentplayer][m]].left;//catch stone values
 stv2=stones[playerhold[currentplayer][m]].right;//catch stone values
 if (swapflag ){tmpstv=stv1;stv1=stv2;stv2=tmpstv;}
  puthalfstone(stv1,midx,midy);
  puthalfstone(stv2,endx,endy);
 
 //setendpointer
  endpointer[curendpoint].connectorcount--;
  cc=standardconnectorcount;
  if (stv1==stv2) cc= doublefaceconnectorcount;
  setendpoint(endx,endy,stv2,cc,endx-midx,endy-midy);
 
 
  playerhold[currentplayer][m]=0;
 showhuman();
 //end of machine
 }

 if(!gameover(currentplayer)) {
 	//setTimeout("nextplayer()",5)
 	alerting("cards left on stack"+stackheight);
	nextplayer();
	}
return;
}

function findspacearoundendpoint(cep){
var endx,endy,midx,midy;
storeresult = new spaceset();
	storeresult.available=false;
	storeresult.midx=-1;
	storeresult.endx=-1;
	storeresult.midy=-1;
	storeresult.endy=-1;


if (endpointer[cep].connectorcount<1) {storeresult.available=false; return storeresult; }
searchstartx =endpointer[cep].x ;
searchstarty =endpointer[cep].y ;
directionx=endpointer[cep].directionx;
directiony=endpointer[cep].directiony;

endx=0;endy=0;
midoptionstart=0;
if(directionx==1 && directiony==0) midoptionstart=0;
if(directionx==-1 && directiony==0) midoptionstart=2; 
if(directionx==0 && directiony==1)  midoptionstart=3;
if(directionx==0 && directiony==-1)  midoptionstart=1;

midoptioncount=0;midoption=midoptionstart;
//for (midoption=0;midoption<5;midoption++) 

while (midoptioncount< 4){
	rememx=0;rememy=0;
	if (midfieldisokay(searchstartx+1,searchstarty) && midoption==3) 	{ rememx=1;  rememy=0; }
	if (midfieldisokay(searchstartx-1,searchstarty) && midoption==1) 	{ rememx=-1;  rememy=0; }
	if (midfieldisokay(searchstartx,searchstarty+1) && midoption==2)	{ rememx=0;  rememy=1; }
	if (midfieldisokay(searchstartx,searchstarty-1) && midoption==0)	{ rememx=0;  rememy=-1; }
	/// useless //if (midfieldisokay(searchstartx+directionx,searchstarty+directiony) && midoption==4) 	{ rememx=directionx;  rememy=directiony; }

	if (!(rememx==0 && rememy==0)) {
		midstartx=searchstartx+rememx;
		midstarty=searchstarty+rememy;
		midstartx=searchstartx+rememx;
		middirx=rememx;middiry=rememy;
		if (endfieldisokay(midstartx+1,midstarty) ) 	{ endx=midstartx+1; endy=midstarty; midx=midstartx;midy=midstarty;}
		if (endfieldisokay(midstartx-1,midstarty) ) 	{ endx=midstartx-1; endy=midstarty;  midx=midstartx;midy=midstarty;}
		if (endfieldisokay(midstartx,midstarty+1) )	{ endx=midstartx;  endy=midstarty+1;  midx=midstartx;midy=midstarty;}
		if (endfieldisokay(midstartx,midstarty-1) )	{ endx=midstartx;  endy=midstarty-1;  midx=midstartx;midy=midstarty;}
		if (endfieldisokay(midstartx+middirx,midstarty+middiry) ) 	{ endx=midstartx+middirx;  endy=midstarty+middiry;  midx=midstartx;;midy=midstarty;}
	}
	midoption++;midoptioncount++;if (midoption>3) midoption=0;
}
if (!(endx==0 && endy==0)) {

	storeresult.available=true;
	storeresult.midx=midx;
	storeresult.endx=endx;
	storeresult.midy=midy;
	storeresult.endy=endy;
	
} else {
	endpointer[cep].connectorcount=0;

}
return storeresult;
}

function fieldisempty(chx,chy) {
if (chx>=0 && chy>=0 && chx<boardsizex && chy<boardsizey )
	if ( fieldarray[chx][chy]==-1 ) return true;
result=false;
}

function fieldisused(chx,chy) {
	if (chx>=0 && chy>=0 && chx<boardsizex && chy<boardsizey ){
		if ( fieldarray[chx][chy]==-1 ) {
			return false;
		} else {
			return true;
		}
	}
	result=false;
}

function midfieldisokay(mdx,mdy){
//return fieldisempty(mdx,mdy);
	if (!(fieldisempty(mdx,mdy))) return false;
	statearound=0;
	if (fieldisused(mdx+1,mdy)) statearound++;
	if (fieldisused(mdx-1,mdy)) statearound++;
	if (fieldisused(mdx,mdy+1)) statearound++;
	if (fieldisused(mdx,mdy-1)) statearound++;
	if (statearound>1) return false;
	return true;
}


function endfieldisokay(eendx,eendy){
;
	if (!(fieldisempty(eendx,eendy))) return false;
	statearound=0;
	if (fieldisused(eendx+1,eendy)) statearound++;
	if (fieldisused(eendx-1,eendy)) statearound++;
	if (fieldisused(eendx,eendy+1)) statearound++;
	if (fieldisused(eendx,eendy-1)) statearound++;
	if (statearound>0) return false;
	return true;
}


function gameover(pl1)
{
sum=0;
for (m2t=0;m2t<currentmaxinventorypos[pl1];m2t++) sum=sum+playerhold[pl1][m2t];
if (sum>0) return false;
if ( stackheight>0) { dealstone(pl1);return false; }
alerting("Player "+pl1+" won!")
showhuman();
addpoints();
has_to_restart=true;
return true;
}

function checkmoveleft()
{
if ( stackheight>0) return false;

stonefound=false
for (n2ep=0;n2ep<maxendpoints;n2ep++){
	epv=endpointer[n2ep].value
	ccc=endpointer[n2ep].connectorcount;
	if (epv> -1 && ccc>0) {
		for (n2p=1;n2p<=maxplayer;n2p++) {
 			for (m2c=0;m2c< maxholding;m2c++) {
  				st2=playerhold[n2p][m2c]
				if (st2>0) { 
					if (stones[st2].left==epv || stones[st2].right==epv ) stonefound=true; 
				}
				
			}
		}
	}
}
if (stonefound) return;
alerting("All player loose");
addpoints();
has_to_restart=true;
return;
}


function sortplayer()
{
//sort all  players
for(n=1;n<=maxplayer;n++)
 { 
sort_only_player(n)
 //finished sort for each player
 }

}


function sort_only_player(n)
{
 for(m=0;m<currentmaxinventorypos[n];m++)
  {
  smallpos=m
  smallvalue=stones[playerhold[n][m]].pointvalue

  //find smallest
  for (i=m;i<currentmaxinventorypos[n];i++)
   {
   if (smallvalue>stones[playerhold[n][i]].pointvalue) 
	{
	smallpos=i;
	smallvalue=stones[playerhold[n][i]].pointvalue;
	}
   }
  //swap smallest with m
  tmp=playerhold[n][m]
  playerhold[n][m]=playerhold[n][smallpos];
  playerhold[n][smallpos]=tmp;
  //select sort for one player finished
  }
  
  for (m=currentmaxinventorypos[n]-1;m>0;m--) if (playerhold[n][m]==0) currentmaxinventorypos[n]=m;
}
function clearfield()
{
	alerting(" ");	

	for (x=0;x<boardsizex;x++) {
		for (y=0;y<boardsizey;y++) {
			puthalfstone("n",x,y);
			fieldarray[x][y]=-1;
		}
	}
	for (n=0;n<maxendpoints;n++){
		endpointer[n].x= -1; 
		endpointer[n].y= -1; 
		endpointer[n].value=-1;
		endpointer[n].connectorcount=-1; 
		endpointer[n].directionx=-1;
		endpointer[n].directiony=-1;
	}
}


function addpoints()
{
for (n=1;n<=maxplayer;n++) 
 {
 for (m=0;m<maxholding;m++) 
  {
  sttmp=playerhold[n][m];
  v=0;
  if (!(sttmp==0)) v=stones[sttmp].pointvalue;
  if(v>15) v-=20;
  playerscores[n] += v;
  }
 }
showscores()
//prepare for score submission through newscore to the highscore.php
//score=playerscores[1]+playerscores[2]+playerscores[3]-playerscores[4]*2
//if (score<0) score=0
//window.document.scoreform.newscore.value=score;
}

//// start with functions that access the user interface  

function showhuman()
{
sortplayer();

   eval("window.document.gameboard.arrow_down.src = '"+imagedir+"arrow_down"+imageext+"'");
   eval("window.document.gameboard.arrow_up.src = '"+imagedir+"arrow_up"+imageext+"'");
   
if (displayonlysteeringplayer){
	if (inventorypos>(currentmaxinventorypos[steeringplayer]-maxvisibleinventorysize)) inventorypos=(currentmaxinventorypos[steeringplayer]-maxvisibleinventorysize);  
	if (inventorypos<0) inventorypos=0;
	if (inventorypos==0)    eval("window.document.gameboard.arrow_down.src = '"+imagedir+"n"+imageext+"'");
	if ((inventorypos+1)>(currentmaxinventorypos[steeringplayer]-maxvisibleinventorysize))    eval("window.document.gameboard.arrow_up.src = '"+imagedir+"n"+imageext+"'");
}

for (pp=1;pp<=maxplayer;pp++){
if ((! (displayonlysteeringplayer) )|| (displayonlysteeringplayer && pp==steeringplayer)) {
 for(m=0;m < maxvisibleinventorysize ; m++) //
  {

  //ts=playerhold[steeringplayer][m];//temp placeholder for the stone
  if (steeringplayer=pp) {
  	ts=playerhold[pp][m+inventorypos];//temp placeholder for the stone
  	
  } else { 
  	ts=playerhold[pp][m];//temp placeholder for the stone
  }
  if (ts==0)
   {
   eval("window.document.gameboard.sm"+(m+1)+"1p"+pp+".src = '"+imagedir+"n"+imageext+"'")
   eval("window.document.gameboard.sm"+(m+1)+"2p"+pp+".src = '"+imagedir+"n"+imageext+"'")
   }
   else
   {
   eval("window.document.gameboard.sm"+(m+1)+"1p"+pp+".src = '"+imagedir+stones[ts].left+""+imageext+"'")
   eval("window.document.gameboard.sm"+(m+1)+"2p"+pp+".src = '"+imagedir+stones[ts].right+""+imageext+"'")
   }
  
  }
  }
 }
}


function puthalfstone(faceval,x,y)
{
	//function has a find or check before being called
	//only sets it in the fieldarray and displays it.
	
	fieldarray[x][y]=faceval;
	eval("window.document.gameboard.c"+x+"r"+y+".src = '"+imagedir+faceval+""+imageext+"'");
	
}

function showscores()
{
for (n=1;n<5;n++) eval("window.document.gameboard.showplayer"+n+".value=playerscores[n]")
return;
}

function clickinventoryup()
{
inventorypos++;
if (displayonlysteeringplayer && inventorypos>currentmaxinventorypos[steeringplayer]-maxvisibleinventorysize)  inventorypos=currentmaxinventorypos[steeringplayer]-maxvisibleinventorysize;
showhuman();
return;

}

function clickinventorydown() 
{
inventorypos--;
if (inventorypos<0)  inventorypos=0;
showhuman();
return;
}

function alerting(alertmsg)
{
window.document.gameboard.alertbox.value=alertmsg
}

// block with interface functions finished

