﻿document.oncontextmenu = disableRightClick;

function disableRightClick() {
  alert('Source code is COPYRIGHTED. Please, do not reproduce.');
  return false;
}

var clone = null;
var glScore;
var glSScore = 0, giMN = 0;
//		var giHs = 23; //vertical distance between cells
//		var gsWs = 27.3; //horizontal distance between cells
var giTx, giTy; // coordinates of the center of the left top cell
var giEx, giEy; // coordinates of the empty cell
var giCx, giCy; // coordinates of the current cell
var gCX, gCY; 
var giCC = 0; // current color
var giSx, giSy, giSc; // saved
var iBallBindValue, iUndoFee, iLevel;
var blnUndoFlag, blnLoad;
var Cell = new Array(92); // array of cells
var Position = new Array(12); // array of row left cell index
var Path1 = new Array(92); // Path[,0]->Y,Path[,1]->X
var Path2 = new Array(92); // Path[,0]->Y,Path[,1]->X
var MoveCellArray1 = new Array(); // giSx - X coordinate of an empty cell
var MoveCellArray2 = new Array(); // giSy - Y coordinate of an empty cell
var MoveCellArray3 = new Array(); // giSc - color  of a current cell
var MoveCellArray4 = new Array(); // glSScore - score fro this position

function Initialize() 
{
  blnLoad = true;
  blnUndoFlag = false;
  glScore = 0;
  giSc = 0;

  giTx = 315;   
  giTy = 141;   
  Position[1] = 0;
  Position[2] = 6;
  Position[3] = 13;
  Position[4] = 21;
  Position[5] = 30;
  Position[6] = 40;
  Position[7] = 51;
  Position[8] = 61;
  Position[9] = 70;
  Position[10] = 78;
  Position[11] = 85;

  document.getElementById("cmdLevel").value = "Novice";
  iBallBindValue = 6;
  iUndoFee = 25;
  iLevel = 3;

  document.onmousedown = Pic_MouseDown;
  if (blnLoad)
    cmdStart_Click();
  else 
    Pic_Paint();
}

function cmdStart_Click() 
{
  var j, k, m;

  blnLoad = false;
  for (m = 0; m < 92; m++) 
  {
    Path1[m] = 0;
    Path2[m] = 0;
    Cell[m] = 0;
  }

  DrawGrayBall(382, 256);

  giMN = 0;
  giEx = 6;
  giEy = 6;
  glScore = 0;
  glSScore = 0;
  document.getElementById("lblScore").value = 0;

  for (k = 1; k < 12; k++) 
  {
    m = GetMax(k);
    for (j = 1; j <= m; j++) 
    {
      Cell[Position[k] + j] = parseInt(iLevel * Math.random() + 2);
    }
  }
  Cell[46] = 1; //Gray
  Pic_Paint();
}

function Pic_Paint() 
{
  var k, j, m, i, X, Y;

  if (Cell[1] >= 1) 
  {
    for (k = 1; k < 12; k++) 
    {
      m = GetMax(k);
      for (j = 1; j <= m; j++) 
      {
        GetXY(k, j)
        i = Cell[Position[k] + j];
        if (i >= 2)
          DrawBall(i, gCX, gCY);
        else
          DrawGrayBall(gCX, gCY);
      }
    }
  }
}

function DrawImage(i, X, Y) 
{
  if (i < 6) 
  {
    var obj = document.getElementById("Ball" + i);
    clone = obj.cloneNode(true);
    clone.style.top = parseInt(Y) + 'px';
    clone.style.left = parseInt(X) + 'px';
    clone.style.visibility = 'visible';
    document.body.appendChild(clone);
  }   
}

function DrawBall(i, X, Y)
{
	DrawImage(i-2, parseInt(X-9), parseInt(Y-9));
}

function DrawGrayBall(X, Y)
{
	DrawImage(5, parseInt(X-9), parseInt(Y-9));
}

function cmdLevel_Click()
{
	switch (document.getElementById("cmdLevel").value)
	{
		case "Novice":
			document.getElementById("cmdLevel").value = "Expert";
			iLevel = 4;
			iBallBindValue = 11;
			iUndoFee = 50;
			break;
		case "Expert":
		  document.getElementById("cmdLevel").value = "Master";
			iLevel = 5;
			iBallBindValue = 21;
			iUndoFee = 100;
			break;
		case "Master":
		  document.getElementById("cmdLevel").value = "Novice";
			iLevel = 3;
			iBallBindValue = 6;
			iUndoFee = 25;
			break;
	}
	cmdStart_Click();
}

function cmdUndo_Click()
{
	if(giSc != 0)
	{
		if(giMN > 0)
			giMN--;
		else
			return;
		giSx = MoveCellArray1[giMN];  //.Sx;
		giSy = MoveCellArray2[giMN];  //.Sy;
		giSc = MoveCellArray3[giMN];  //.Color;
		glSScore = MoveCellArray4[giMN];  //.Score;

		giCx = giSx;
		giCy = giSy;
		giCC = giSc;
		glScore = parseInt(document.getElementById("lblScore").value) - iUndoFee;
		document.getElementById("lblScore").value = glScore;

		blnUndoFlag = true;
		CellMove();
		blnUndoFlag = false;
	}
}

function GetMax(y)
{
	var m;

	if(y < 6)
		m = 5 + y;
	else
		m = 17 - y;
	return m;
}

function BorderCheck(x, y)
{
	if(x < 1 || x > GetMax(y) || y < 1 || y > 11) 
		return false; 
	else
		return true;
}

function CheckCC(x, y)
{	
	// Compares color of cell with giCC, y-vertical coordinate, x-horizontal
	if(x == giCx && y == giCy) 
		return false; //exclude current cell
	if(!BorderCheck(x, y))
		return false; //check the border
	if(giCC == Cell[Position[y] + x]) 
		return true; 
	return false; 
}
	
function CellMove()
{
	var i, j;

	if (giCC != 0)
	{
		GetXY(giEy, giEx);
		DrawBall(giCC, gCX, gCY);
		GetXY(giCy, giCx);
		DrawGrayBall(gCX, gCY);
		i = Position[giEy] + giEx;
		j = Position[giCy] + giCx;
		Cell[i] = Cell[j];
		Cell[j] = 1;
		giSx = giEx;
		giSy = giEy;
		giSc = giCC;
		giEx = giCx;
		giEy = giCy;
		if (blnUndoFlag == false) 
		{
		  MoveCellArray1[giMN] = giSx;
		  MoveCellArray2[giMN] = giSy;
		  MoveCellArray3[giMN] = giSc;
		  MoveCellArray4[giMN] = glSScore;
		  giMN++;
		}
	}
}

function CntLinks(x, y)
{
	var iCnt;

	iCnt = 0;
	if(CheckCC(x + 1, y)) iCnt++;
	if(CheckCC(x, y + 1)) iCnt++;
	if(CheckCC(x - 1, y)) iCnt++;

	if(y < 6)
	{
		if(CheckCC(x - 1, y - 1)) iCnt++;
		if(CheckCC(x, y - 1)) iCnt++;
		if(CheckCC(x + 1, y + 1)) iCnt++;
	}
	else
	{
		if(y > 6)
		{
			if(CheckCC(x, y - 1)) iCnt++;
			if(CheckCC(x + 1, y - 1)) iCnt++;
			if(CheckCC(x - 1, y + 1)) iCnt++;
		}
		else
		{
			if(CheckCC(x - 1, y - 1)) iCnt++;
			if(CheckCC(x, y - 1)) iCnt++;
			if(CheckCC(x - 1, y + 1)) iCnt++;
		}
	}
	return iCnt;
}

function FindPath()
{
	var i, x, y, m, n;

	for(m=1;m<92;m++)
	{
		Path1[m] = 0;
	}
	Path1[1] = giCy;
	Path2[1] = giCx;
	m = 1;
	n = 1;
	while(true)
	{
		while(IsNext(m))
		{
			m++;
			if (Cell[ Position[Path1[m]] + Path2[m] ] == 1)
				return true;
		}
			        
		if(m == n) 
			return false;
	  y = Path1[m];
	  x = Path2[m];
		for(i=m; i>=n+1; i--)
		{
		  Path1[i] = Path1[i - 1];
		  Path2[i] = Path2[i - 1];
		}
		Path1[n] = y;
		Path2[n] = x;
		n++;
	}
}

function FindNext(x, y)
{
	var i, n;

	if(!BorderCheck(x, y))
		return false; //check the border
	for(i=1;i<92;i++)
	{
	  if (Path1[i] == 0) 
			break;
	  if (Path1[i] == y && Path2[i] == x) 
			return false;
	}
  
	n = Position[y] + x;
	if(giCC == Cell[n] || Cell[n] == 1) // the same color or empty space
	{
	  Path1[i] = y;
	  Path2[i] = x;
		return true;  
	}
	return false;  
}

function GetXY(k, j)
{
  //get pixels coordinates
  //gCY = parseInt(giTy + (k - 1) * giHs);
  //gCX = giTx - (GetMax(k) - 6) * gsWs / 2 + (j - 1) * gsWs;
  gCY = parseInt(giTy + (k - 1) * 23);
	gCX = parseInt(giTx - parseFloat((GetMax(k) - 6) * 13.65) + parseFloat((j - 1) * 27.3));
}

function IsNext(iPath)
{
	var y, x;

	y = Path1[iPath];
	x = Path2[iPath];

	if(y < 6)
	{
		if(FindNext(x + 1, y)) return true;
		if(FindNext(x, y - 1)) return true;
		if(FindNext(x - 1, y - 1)) return true;
		if(FindNext(x - 1, y)) return true;
		if(FindNext(x, y + 1)) return true;
		if(FindNext(x + 1, y + 1)) return true;
	}
	else
	{
		if(y > 6)
		{
			if(FindNext(x + 1, y)) return true;
			if(FindNext(x + 1, y - 1)) return true;
			if(FindNext(x, y - 1)) return true;
			if(FindNext(x - 1, y)) return true;
			if(FindNext(x - 1, y + 1)) return true;
			if(FindNext(x, y + 1)) return true;
		}
		else
		{
			if(FindNext(x + 1, y)) return true;
			if(FindNext(x, y - 1)) return true;
			if(FindNext(x - 1, y - 1)) return true;
			if(FindNext(x - 1, y)) return true;
			if(FindNext(x - 1, y + 1)) return true;
			if(FindNext(x, y + 1)) return true;
		}
	}
	return false;
}

function Pic_Click()
{
	blnUndoFlag = false;
	CellMove();
}

function Pic_MouseDown()
{
  var i, x0, X, Y;
  var x1, y1, x2, y2, iCnt;
  var dx, dy;
  //debugger;
	X = window.event.clientX;
	Y = window.event.clientY;
	window.event.cancelBubble = true;
	//window.status = 'X=' + window.event.clientX + ' Y=' + window.event.clientY;		
	
	//giCy = parseInt((Y - giTy + giHs / 2) / giHs) + 1;    //row #
	giCy = parseInt( parseFloat((Y - giTy + 11.5) / 23) + 1);    //row #

	//x0 = parseInt(giTx - (GetMax(giCy) - 6) * gsWs / 2);
	x0 = parseInt(giTx - parseFloat((GetMax(giCy) - 6) * 13.65));
	giCx = parseInt(parseFloat(((X - x0) / 27.3 + 0.5)) + 1);       //# of cell in row
  
	if(!BorderCheck(giCx, giCy))
	{
		giCC = 0;
		return;
	}
  
	giCC = Cell[Position[giCy] + giCx];     //color of the clicked cell
	for(i=2;i<7;i++)
		if(giCC == i) break;   //# in color table
	if(i > 6)     //not a ball
	{
		giCC = 0;
		return;
	}

	// Check for allowed move
	iCnt = CntLinks(giEx, giEy);

	if(iCnt == 0 )
	{
		giCC = 0;
		return;
	}
	else   //Are the empty cell and current cell neighbours?
	{
	  GetXY(giCy, giCx);
	  x1 = gCX;
	  y1 = gCY;
		GetXY(giEy, giEx);
		x2 = gCX;
		y2 = gCY;
		dx = x1 - x2;
		dy = y1 - y2;
		//if ((parseFloat(dx * dx) + parseFloat(dy * dy)) > parseFloat(gsWs * gsWs * 1.1))
		if ((parseFloat(dx * dx) + parseFloat(dy * dy)) > 819.819)
		{
			if(iCnt < 2 || FindPath()==false)
			{
				giCC = 0;     //current color=0 -> not neighbours
				return;
			}
		}
		iCnt -= CntLinks(giCx, giCy);
		glSScore = glScore;
		glScore = glScore + parseInt(iCnt * iBallBindValue) - 1;
		document.getElementById("lblScore").value = glScore;
		Pic_Click();
	}
}


