

	function Puzzle(x,y,w,h,img,xsize,ysize,txt) {
		this.Dynlayer=DynLayer;
		this.Dynlayer(null,x,y,w,h);
		
		this.w = w;
		this.h = h;
		this.img = img;
		this.xsize = xsize;
		this.ysize = ysize;

		this.cardw = w/xsize;
		this.cardh = h/ysize;
		this._txt = txt;
		this._dobackshift = false;
		this._emptyx = xsize-1;
		this._emptyy = ysize-1;
		this._solveRotateCCW = true;
		this._backshift = new Array(xsize*ysize);
		this._xmydebug=false;
		this.imghtml = '<img src="' + img + '" width="' + w + '" height="' + h + '">';
		this.columns = new Array(this.colcount);
		//alert(this.imghtml );
		this.onPreCreate(Puzzle.PreCreate);
		this.onCreate(function() { this.addEventListener(Puzzle.listener); });
//		DragEvent.enableDragEvents(this);

	}
	var p = dynapi.setPrototype('Puzzle','DynLayer');
	Puzzle.PreCreate = function() {
		this.setBgColor(this._bgcolor)	

		// create child layer for caption
		this.addChild(new DynLayer(null,1,1,this.w,this.h),'dyncaption');
		this.addChild(new DynLayer(null,1,1,1,1),'solvetimer');
		this.solvetimer._step = 0;
		this.solvetimer.addEventListener({
		ontimer:function(e){
				myPuzzle.solvetimer._step = myPuzzle.solvetimer._step+1
				solvePuzzleOnce();
				solvePuzzleOnce();
				solvePuzzleOnce();
				slidePuzzlePieces();
//				alert(myPuzzle.solvetimer._step);
				if (myPuzzle.solvetimer._step>4) {
					myPuzzle.solvetimer._step = 0;
					myPuzzle.solvetimer.stopTimer();
					shufflebutton.setVisible(true);
					//setPuzzlePieces();
				}
			}
		} );


		this.addChild(new DynLayer(null,1,1,1,1),'solvenexttimer');
		this.solvenexttimer._step = 0;
		this.solvenexttimer.addEventListener({
		ontimer:function(e){
				myPuzzle.solvenexttimer._step = myPuzzle.solvenexttimer._step+1
				doSolveStep();
				if (isSolved()){
				//	alert('SOLVED')
					myPuzzle.solvenexttimer.stopTimer();
					myPuzzle.solvetimer.stopTimer();
					shufflebutton.setVisible(true);
						if (myPuzzle._continueaftersolve) {
							myPuzzle._loopcount = 0;
							myPuzzle.startTimer(myPuzzle._loopinterval,0);
						}
				}
			}
		} );
		
		var i = 0;		
		var j = 0;
		var newimgx = 0;
		var newimgy = 0;		
		var ch = null;
		var ccount = -1;
				//alert('build start');
		for (i=0; i<this.xsize; i++){
			this.columns[i]= new Array(this.ysize);
			for (j=0; j<this.ysize; j++){
				ccount++;
				if (!(i==this.xsize-1 && j==this.ysize-1)){
					ch = null;
					if (this._txt!=null){
						var ccpos = i + (j*this.xsize);
						if (ccpos < this._txt.length){
							ch = this._txt.charAt(ccpos);
						}
					} 
					this.columns[i][j] = new PuzzleElement(i*this.cardw,j*this.cardh,this.cardw,this.cardh,this.w,this.h,-(i*this.cardw),-(j*this.cardh),this.imghtml, ch,1,this._textcolor);
					if (this._textbgcolor!=null){
						this.columns[i][j].setBgColor(this._textbgcolor);
					}
					this.columns[i][j]._initx = i;
					this.columns[i][j]._inity = j;
					this.columns[i][j]._currentx = i;
					this.columns[i][j]._currenty = j;
				
					if (this._grid) this.columns[i][j].setInnerBorder(1,this._gridcolor);
					this.addChild(this.columns[i][j]);
					
					
				}
			}

		}

		//alert('build done');
		if (this._startupsolved==false){
			var times = myPuzzle.xsize * myPuzzle.ysize * 10; 
			for (i=0 ;i<times;i++){
				shuffleOnce();
			}
			setPuzzlePieces();
		}
		

//		this.slidebutton = new DynLayer(null,this.solvebutton.getX() + this.solvebutton.getWidth()+2,0,btw,bth);
//		this.slidebutton.setBorder(1,'gray');
//		this.slidebutton.setBgColor('#cc0033');
//		if (this._slide==true){
//			this.slidebutton.setHTML('<center><b>slide off</b></center>');
//		} else {
//			this.slidebutton.setHTML('<center><b>slide on</b></center>');
//		}

//		this.slidebutton.setCursor('default');
//		this.slidebutton.addEventListener({
//			onclick:function(e){
			//	myPuzzle.slidebutton.setVisible(false);
//				myPuzzle._slide =  !myPuzzle._slide;
//				if (myPuzzle._slide==true){
//					myPuzzle.slidebutton.setHTML('<center><b>slide off</b></center>');
//				} else {
//					myPuzzle.slidebutton.setHTML('<center><b>slide on</b></center>');
//				}

//			}
		
//		});
//		this.dynmenu.addChild(this.slidebutton);

		this.myadd= new DynLayer(null,this.w-88  ,this.h-12,120,20);
		this.myadd.setHTML('<a href="http://www.matrixpuzzles.com" target="_blank" class="myadd" >matrixpuzzles.com<\/a>');
		if (this._hl) this.myadd.setVisible(false);
		
		this.addChild(this.myadd);
		this.setVisible(true); // make sure the widget is visible
		this._iscreated = true;
		// add layer for event handling
	//	this.dynevents = new DynLayer(null,0,0,this.w,this.h); 
	//	this.addChild(this.dynevents);

	};
	Puzzle.listener = {


	}

function shiftPieceToEmptyPosition(piece){
//	var piece1 = myPuzzle.columns[myPuzzle.curr	entx][myPuzzle.emtyy];
	//alert('shiftPieceToEmptyPosition')
	if (isAdjecting(piece._currentx,piece._currenty,myPuzzle._emptyx,myPuzzle._emptyy)){
	//	alert(piece.w)
		var nx = piece._currentx;
		var ny = piece._currenty;
		piece._currentx = myPuzzle._emptyx;
		piece._currenty = myPuzzle._emptyy;
		myPuzzle._emptyx = nx;
		myPuzzle._emptyy = ny;
		myPuzzle.columns[piece._currentx][piece._currenty] = piece;
		myPuzzle.columns[myPuzzle._emptyx][myPuzzle._emptyy] = null;

	//	piece.slideTo(piece._currentx*piece.w,piece._currenty*piece.h);
//		piece.setX(piece._currentx*piece.w);
//		piece.setY(piece._currenty*piece.h);
	}

}

function isNearEmptyXY(x,y){
 
	return isAdjecting(x,y,myPuzzle._emptyx,myPuzzle._emptyy);
}

function isNearEmpty(piece){
 
	return isAdjecting(piece._currentx,piece._currenty,myPuzzle._emptyx,myPuzzle._emptyy);
}

function isAdjecting(x1,y1,x2,y2){
//	var piece1 = myPuzzle.columns[myPuzzle.currentx][myPuzzle.emtyy];
	if (x1==x2+1 && y1==y2) return (true);
	if (x1==x2-1 && y1==y2) return (true);
	if (x1==x2 && y1==y2-1) return (true);
	if (x1==x2 && y1==y2+1) return (true);
	
	return false;
}
function shufflePuzzle(times){
	var i = 0;
	for (i=0 ;i<times;i++){
		shuffleOnce();
	}
	
	slidePuzzlePieces();
	//piece.slideTo(piece._currentx*piece.w,piece._currenty*piece.h);
}

function shufflePuzzleTimes(){
	var i = 0;
	var times = myPuzzle.xsize * myPuzzle.ysize * 10; 
	for (i=0 ;i<times;i++){
		shuffleOnce();
	}
	
	slidePuzzlePieces();
	//piece.slideTo(piece._currentx*piece.w,piece._currenty*piece.h);
}

function slidePuzzlePieces(){
	var x = 0
	var y = 0;
	//alert('slidePuzzlePieces');

	for (x=0;x<myPuzzle.xsize;x++){
		for (y=0;y<myPuzzle.ysize;y++){
			if (!(x==myPuzzle._emptyx && y==myPuzzle._emptyy )){
				if (myPuzzle.columns[x][y]!=null){
					if (myPuzzle._slide){
					//	myPuzzle.columns[x][y].slideStop();
					//	myPuzzle.columns[x][y].slideTo(myPuzzle.columns[x][y]._currentx*myPuzzle.columns[x][y].w,myPuzzle.columns[x][y]._currenty*myPuzzle.columns[x][y].h);
						myPuzzle.columns[x][y].slideTo(myPuzzle.columns[x][y]._currentx*myPuzzle.columns[x][y].w,myPuzzle.columns[x][y]._currenty*myPuzzle.columns[x][y].h,myPuzzle._slideinc,myPuzzle._slidespeed);
	
					} else{
						myPuzzle.columns[x][y].setX(myPuzzle.columns[x][y]._currentx*myPuzzle.columns[x][y].w);
						myPuzzle.columns[x][y].setY(myPuzzle.columns[x][y]._currenty*myPuzzle.columns[x][y].h);
					}
					
				}
				
			}
			
		}
	}
	//piece.slideTo(piece._currentx*piece.w,piece._currenty*piece.h);
		//alert('slidePuzzlePieces done');
}
function setPuzzlePieces(){
	var x = 0
	var y = 0;
		//alert( 'setPuzzlePieces');
//	//alert(myPuzzle._slide);
	slideStop();
	for (x=0;x<myPuzzle.xsize;x++){
		for (y=0;y<myPuzzle.ysize;y++){
			if (!(x==myPuzzle._emptyx && y==myPuzzle._emptyy )){
				if (myPuzzle.columns[x][y]!=null){
						myPuzzle.columns[x][y].setX(myPuzzle.columns[x][y]._currentx*myPuzzle.columns[x][y].w);
						myPuzzle.columns[x][y].setY(myPuzzle.columns[x][y]._currenty*myPuzzle.columns[x][y].h);
				}
				
			}
			
		}
	}
	//piece.slideTo(piece._currentx*piece.w,piece._currenty*piece.h);
}

function slideStop(){
	var x = 0
	var y = 0;
	//alert( 'slideStop');
//	//alert(myPuzzle._slide);
	for (x=0;x<myPuzzle.xsize;x++){
		for (y=0;y<myPuzzle.ysize;y++){
			if (!(x==myPuzzle._emptyx && y==myPuzzle._emptyy )){
				if (myPuzzle.columns[x][y]!=null){
					if (myPuzzle._slide){
						myPuzzle.columns[x][y].slideStop();
					}
					
				}
				
			}
			
		}
	}
		//alert( 'slideStop Done');
	//piece.slideTo(piece._currentx*piece.w,piece._currenty*piece.h);
}

function swapWithEmpty(piece){
		//alert( 'swapWithEmpty');
	var nx = piece._currentx;
	var ny = piece._currenty;
	piece._currentx = myPuzzle._emptyx;
	piece._currenty = myPuzzle._emptyy;
	myPuzzle._emptyx = nx;
	myPuzzle._emptyy = ny;
	myPuzzle.columns[piece._currentx][piece._currenty] = piece;
	myPuzzle.columns[myPuzzle._emptyx][myPuzzle._emptyy] = null;

	//alert( 'swapWithEmpty done');
}
function solvePuzzle(){
solvePuzzleOnce();
solvePuzzleOnce();
solvePuzzleOnce();
slidePuzzlePieces();
}
function solvePuzzleOnce(){
	var x = 0
	var y = 0;
	
	var occx = 0;
		//alert( 'solvePuzzleOnce');

	for (x=0;x<myPuzzle.xsize;x++){
		for (y=0;y<myPuzzle.ysize;y++){
			if (!(x==myPuzzle._emptyx && y==myPuzzle._emptyy )){
				if (myPuzzle.columns[x][y]!=null){
				
			//	alert(myPuzzle.columns[x][y]._currentx)
				if (!(myPuzzle.columns[x][y]._initx==myPuzzle.columns[x][y]._currentx && myPuzzle.columns[x][y]._inity==myPuzzle.columns[x][y]._currenty ) ){


					if (!(myPuzzle.columns[x][y]._initx==myPuzzle._emptyx && myPuzzle.columns[x][y]._inity==myPuzzle._emptyy ) ){
						swapWithEmpty(myPuzzle.columns[myPuzzle.columns[x][y]._initx][myPuzzle.columns[x][y]._inity]);
						swapWithEmpty(myPuzzle.columns[x][y]);
					}else{
						swapWithEmpty(myPuzzle.columns[x][y]);
					
					}
				
				}

											
//					
				}
				
			}
			
		}
	}
	
			//alert( 'solvePuzzleOnce done');

	//piece.slideTo(piece._currentx*piece.w,piece._currenty*piece.h);
}

 function shuffleOnce(){
 				//alert('shuffleOnce');
	try{
	var rnd = getRandomInt(4.9);
	var pc = null;
	var ex = myPuzzle._emptyx;
	var ey = myPuzzle._emptyy;
	var px = 0;
	var py = 0;
//	alert(rnd)
	if (rnd<=1){
		px = ex;
		py = ey-1;
	}else 	if (rnd==2){
		px = ex+1;
		py = ey;
	}else	if (rnd==3){
		px = ex;
		py = ey+1;
	}else 	if (rnd==4){
		px = ex-1;
		py = ey;
	}
	var strt = 'px=' + px + '  py=' + py + '  /  ex=' + ex + '  ey=' + ey;
//	alert (strt);

	if (px<0) px=0;
	if (py<0) py=0;

	if (px>=myPuzzle.xsize ) px=myPuzzle.xsize - 1;
	if (py>=myPuzzle.ysize ) py=myPuzzle.ysize - 1;
	if (!(px==ex && py==ey)){
		if (myPuzzle.columns[px][py]!=null){
			var piece = myPuzzle.columns[px][py];
			shiftPieceToEmptyPosition(piece);
		}
	} //else alert( 'same');
	
	}catch (err){
	
	}
	//alert( 'shuffleonce done');
}
function getRandomInt(intval){
	return (Math.round(intval * Math.random()));
}


function startPuzzleLoop(){
				myPuzzle._loop =  true;
				myPuzzle._loopcount = 0;
				if (myPuzzle._loop==true){
					myPuzzle.autobutton.setHTML('<center><b><small>stop<\/small><\/b><\/center>');
					myPuzzle.stopTimer();
					myPuzzle.startTimer(myPuzzle._loopinterval,0);

				} else {
					myPuzzle.stopTimer();
					myPuzzle.autobutton.setHTML('<center><b><small>loop<\/small><\/b><\/center>');
				}

}
function stopPuzzleLoop(){

				myPuzzle._loop =  false;
				if (myPuzzle._loop==true){
					myPuzzle.autobutton.setHTML('<center><b><small>stop<\/small><\/b><\/center>');
					myPuzzle.stopTimer();
					myPuzzle.startTimer(myPuzzle._loopinterval,0);

				} else {
					myPuzzle.stopTimer();
					myPuzzle.autobutton.setHTML('<center><b><small>loop<\/small><\/b><\/center>');
				}

}

function doSolveStep(){
	var nx = 0;
	var ny = 0;
	
	var cx = 0;
	var cy = 0;
	var cpiece = null;
	
	var x = 0;
	var y = 0;
	var dtx = -1;
	var dty = -1;
	var found = false;
//	alert('solvenext');

	if (myPuzzle._dobackshift){
	//	alert('BACKSHIFT');
	
		pcLIFO=backshiftLIFO();
		if (pcLIFO!=null){
			if (isNearEmpty(pcLIFO)){
	//			alert('BACKSHIFT OK');
				swapWithEmpty(pcLIFO);
				slidePuzzlePieces();
				return;
			}else{
				alert('BACKSHIFT FAIL A');

				clearBackShift();			
				myPuzzle._dobackshift = false;
			}
		}else{
			//	alert('BACKSHIFT FAIL B');
		
			myPuzzle._dobackshift = false;

		}
		
	}
	
	for (y=0;y<myPuzzle.ysize && !found;y++){
		for (x=0;x<myPuzzle.xsize && !found;x++){
				if (myPuzzle.columns[x][y]!=null){ 
					if (!inBackShift(x,y) && (myPuzzle.columns[x][y]._initx != myPuzzle.columns[x][y]._currentx || myPuzzle.columns[x][y]._inity != myPuzzle.columns[x][y]._currenty)){
						nx = x;
						ny = y;
						found = true;					
					}else {
						dtx = x;
						dty = y;
					
					}					
				}else {
						nx = x;
						ny = y;
						if (!inBackShift(x,y)) {
							found = true;					
						}else {
							dtx = x;
							dty = y;
						}
				}
		}//END LOOP Y

	}//END LOOP X
	
	if (myPuzzle.ysize==2 || dty>=myPuzzle.ysize-2 || ( dty==myPuzzle.ysize-3 && dtx == myPuzzle.xsize-1 ) ){
		SortLastTwoRows();
	return;
	}

	found = false;					
	
		for (y=0;y<myPuzzle.ysize && !found;y++){
		for (x=0;x<myPuzzle.xsize && !found;x++){
			if (!(x==myPuzzle._emptyx && y==myPuzzle._emptyy )){
				if (myPuzzle.columns[x][y]!=null){ 
					if (myPuzzle.columns[x][y]._initx == nx && myPuzzle.columns[x][y]._inity == ny){
						cx = x;
						cy = y;
						cpiece = myPuzzle.columns[x][y];
						found = true;
						
					}					
				}else{
				
				
				}
			}
		}//END LOOP Y

	}//END LOOP X
	var npx = cx;
	var npy = cy;

	
	if (nx < cx)
		npx = npx-1;
	else 	if (nx > cx)
		npx = npx+1;
	else if (ny < cy)
		npy = npy-1;
	else alert('oops solvenext');

	var shiftx = myPuzzle._emptyx;
	var shifty = myPuzzle._emptyy;

	if (myPuzzle._emptyy> npy && !(myPuzzle._emptyx==cpiece._currentx && myPuzzle._emptyy-1==cpiece._currenty ) )
		shifty = myPuzzle._emptyy-1;
	else if (myPuzzle._emptyy< npy && !(myPuzzle._emptyx==cpiece._currentx && myPuzzle._emptyy+1==cpiece._currenty ) )
		shifty = myPuzzle._emptyy+1;
	else 	if (myPuzzle._emptyx< npx && !(myPuzzle._emptyx+1==cpiece._currentx && myPuzzle._emptyy==cpiece._currenty ) )
		shiftx = myPuzzle._emptyx+1;
	else	if (myPuzzle._emptyx> npx && !(myPuzzle._emptyx-1==cpiece._currentx && myPuzzle._emptyy==cpiece._currenty ) )
		shiftx = myPuzzle._emptyx-1;
	else 	if (!(myPuzzle._emptyx==cpiece._currentx && myPuzzle._emptyy+1==cpiece._currenty ) )
		shifty = myPuzzle._emptyy+1;
		
	else 	if (!(myPuzzle._emptyx+1==cpiece._currentx && myPuzzle._emptyy==cpiece._currenty ) )
		shiftx = myPuzzle._emptyx+1;

	
	//else alert('oops solvenext');


	//get PATH TO EMPTY
	var path = null;
	var pathcomplete = false;
	var cc=0;
	var curcard = myPuzzle.columns[npx][npy];
	var shiftpiece = null;
	
	var endpiece = curcard;

	if (endpiece ==null ){
		shiftpiece = myPuzzle.columns[cx][cy];
		if (!backShiftIsEmpty()){
			if (backShiftCount()==3){
				myPuzzle._backshift[3] = myPuzzle.columns[cx-1][cy];
				myPuzzle._dobackshift = true;
			}else alert('backshift length is invalid: ' + backShiftCount());					
							
		}//else alert('backshift is empty');					

	}else {
		var specialPath = true;
	//	alert ('special path dtx=' + dtx + ' dty=' + dty );

		if (cx==myPuzzle.xsize-1 && npx==myPuzzle.xsize-1 && dtx+1==cx && dty+1==cy){
			
			if (!(cx-2== myPuzzle._emptyx && cy == myPuzzle._emptyy) && backShiftIsEmpty()){
				path = getNormalPath(cx-2,cy,cx,cy,myPuzzle._emptyx,myPuzzle._emptyy, dtx,dty);
				//	alert ('special path A');

			}else if ((cx-2== myPuzzle._emptyx && cy == myPuzzle._emptyy) ){
				path = new Array(1);
				path[0]=getPiece(cx-2,cy-1);
				addToBackShift(path[0]);
				//alert ('special path B');
			
			}else if ((cx-2== myPuzzle._emptyx && cy-1 == myPuzzle._emptyy) ){
				path = new Array(1);
				path[0]=getPiece(cx-1,cy-1);
				addToBackShift(path[0]);
			//	alert ('special path C');
			}else if ((cx-1== myPuzzle._emptyx && cy-1 == myPuzzle._emptyy) ){
				path = new Array(1);
				path[0]=getPiece(cx,cy-1);
				addToBackShift(path[0]);
			//	alert ('special path D');
			} else
			alert ('special path  UNDEFINED');

		} else 	if (dty== myPuzzle.ysize-1-1 && cy== myPuzzle.ysize-1) {
				path = new Array(1);
				var pccc = ccwRotateLastTwoRowsPiece();
				path[0]=pccc;
				alert ('special path PLR ' + pccc._currentx + '/' + pccc._currenty);


		} else 	if (dty== myPuzzle.ysize-1) {
				path = new Array(1);
				var pccc = ccwrRotateLastTwoRowsPiece();
				path[0]=pccc;
				alert ('special path LR ' + pccc._currentx + '/' + pccc._currenty);
		} else{
			specialPath = false;
	//		alert('getNormalPath ' + npx + '/' + npy);
			path = getNormalPath(npx,npy,cx,cy,myPuzzle._emptyx,myPuzzle._emptyy, dtx,dty);
		}
		
		if (path!=null ){
		//	alert ('path found ' + path.length);
			var lastcard = null;
			var ci = 0;
			for (ci=0; ci<path.length; ci++){
				if (path[ci]!=null) lastcard = path[ci];
			}
			shiftpiece = lastcard;
		}else if (!specialPath){
			shiftpiece = lastcard;
		}
//		shiftpiece = myPuzzle.columns[shiftx][shifty];

//		while(!pathcomplete && cc<1000){
//			cc++;
	
//		}
//		if (!pathcomplete) alert( 'path not found');
	
	}
	
	
	if (shiftpiece!=null){
		
		if (isNearEmpty(shiftpiece)){
			//alert('shift OK');
			swapWithEmpty(shiftpiece);
			slidePuzzlePieces();
		} else {
			//	alert('shift NOT OK: NOT NEAR EMPTY');
				shiftpiece = getPiece(myPuzzle._emptyx,myPuzzle._emptyy-1);
				if (isNearEmpty(shiftpiece)){
					//alert('SECOND shift OK');
					swapWithEmpty(shiftpiece);
					slidePuzzlePieces();
				}
		}
		
	}
//	alert('nx=' + nx + ' ny=' + ny);
//	alert('cx=' + cx + ' cy=' + cy);
//	alert('npx=' + npx + ' npy=' + npy);
//	alert('shiftx=' + shiftx + ' shifty=' + shifty);
	
	
}

function getPiece( x, y){
	if (myPuzzle.columns[x][y]==null) return null 
		else
	return myPuzzle.columns[x][y];
}

function getNormalPath( stx, sty, cx,cy, ex,ey,dtx,dty ){
	var mx = myPuzzle.xsize - 1;
	var my = myPuzzle.ysize - 1;
	var rx=0;
	var ry=0;
	var piece = null;
	var patharr = new Array(myPuzzle.xsize*myPuzzle.ysize);
	if (cx==mx && stx==mx && dtx+1==cx && dty+1==cy){
		alert('getNormalPath: on Xedge');
		return null;
	}else{
		var ended = false;
		var cc=1;
		var tx=stx;
		var ty=sty;
		patharr[0]=getPiece(stx,sty);
		while(!ended && (cc<=mx*my) ){
//					alert ('getNextNormalPathCard: ' + tx + '/' + ty);
			piece = getNextNormalPathCard( tx, ty, cx,cy, ex,ey, dtx, dty );
			if (piece!=null){
				patharr[cc]=piece;
				tx = piece._currentx;
				ty = piece._currenty;
		//		alert ('pathPiece: ' + tx + '/' + ty);
			}else{
				ended=true;
			}
			
			cc++;	
		}
			
	}
	return patharr;
}

function shiftPieceTo( stx, sty, cx,cy, ex,ey,dtx,dty ){
	var patharr = null;
//	dtx = cx;
//	dty = cy;
	if (myPuzzle._emptyx==stx && myPuzzle._emptyy==sty){
			patharr = new Array(1);
			var pc = getPiece(cx,cy);
			if (pc!=null)
				patharr[0]=getPiece(cx,cy);
			
			return patharr;
	}else return getNormalPathLastTwo( stx, sty, cx,cy, ex,ey,dtx,dty )

}

function getNormalPathLastTwo( stx, sty, cx,cy, ex,ey,dtx,dty ){
//alert('getNormalPathLastTwoRows');
	var mx = myPuzzle.xsize - 1;
	var my = myPuzzle.ysize - 1;
	var rx=0;
	var ry=0;
	var piece = null;
	var patharr = new Array(myPuzzle.xsize*myPuzzle.ysize);
//	if (stx==ex && sty==ey){
//		patharr[0]=getPiece(cx,cy);
//	}else 
	if (cx==mx && stx==mx && dtx+1==cx && dty+1==cy){
		alert('getNormalPath: on Xedge');
		return null;
	}else{
		var ended = false;
		var cc=1;
		var tx=stx;
		var ty=sty;
		patharr[0]=getPiece(stx,sty);
		while(!ended && (cc<=mx*my) ){
//					alert ('getNextNormalPathCard: ' + tx + '/' + ty);
			piece = getNextNormalPathCardLastTwo( tx, ty, cx,cy, ex,ey, dtx, dty );
			if (piece!=null){
				patharr[cc]=piece;
				tx = piece._currentx;
				ty = piece._currenty;
		//		alert ('pathPiece: ' + tx + '/' + ty);
			}else{
				ended=true;
			}
			
			cc++;	
		}
			
	}
	return patharr;
}
	

function getNextNormalPathCard( stx, sty, cx,cy, ex,ey ,dtx,dty){
	var mx = myPuzzle.xsize - 1;
	var my = myPuzzle.ysize - 1;
	var rx=0;
	var ry=0;
	var piece = null;
	if (isNearEmptyXY(stx,sty)){
		return null;
	}
	//alert('request pathcard:' + stx + '/' + sty +  '  c:' + cx  + '/' + cy +  '  e:' + ex  + '/' + ey );

		if   (!(sty + 1 == cy && stx == cx) && !(sty + 1 == dty && stx == dtx) && (sty < ey  ) && sty<my)  {
			rx = stx ;
			ry = sty + 1;
//		} else 		if   (!(sty - 1 == cy && stx == cx) && !(sty - 1 == dty && stx == dtx) && (cy == ey  ) && sty>0 && (stx<=ex && cx<ex ) ) {
//			rx = stx ;
//			ry = sty - 1;
		} else if   (!(sty  == cy && stx+1 == cx) && !(sty  == dty && stx+1 == dtx) && (stx < ex  ) && stx<mx )  {
			rx = stx + 1;
			ry = sty ;
		} else if   (!(sty  == cy && stx-1 == cx) && !(sty  == dty && stx-1 == dtx) && (ex<stx) && stx>0)  {
			rx = stx - 1;
			ry = sty ;

		} else if   (!(sty - 1 == cy && stx == cx) && !(sty - 1 == dty && stx == dtx) && (sty > ey  ) && sty>0 )  {
			rx = stx;
			ry = sty-1;
			
		} else if   (!(sty  == cy && stx-1 == cx) && !(sty  == dty && stx-1 == dtx) && (stx > ex  ) && stx>0)  {
			rx = stx - 1;
			ry = sty;
		}else 		if   (!(sty + 1 == cy && stx == cx) && !(sty + 1 == dty && stx == dtx)  && sty<my)  {
			rx = stx ;
			ry = sty + 1;
		} else if   (!(sty  == cy && stx+1 == cx) && !(sty  == dty && stx+1 == dtx)    && stx<mx ){
			rx = stx + 1;
			ry = sty ;
		} else if   (!(sty  == cy && stx-1 == cx) && !(sty  == dty && stx-1 == dtx)   && stx>0)  {
			rx = stx - 1;
			ry = sty;
		} else if   (!(sty -1 == cy && stx == cx) && !(sty -1 == dty && stx == dtx)  && sty>0)  {
			rx = stx ;
			ry = sty-1;
		} else  if(stx<mx && !(sty  == dty && stx+1 == dtx)) {
			rx = stx + 1 ;
			ry = sty;
		} else  if(sty<my  && !(sty + 1 == dty && stx == dtx)) {
			rx = stx  ;
			ry = sty+1;
		} else  if(stx>0 && !(sty  == dty && stx-1 == dtx)) {
			rx = stx - 1 ;
			ry = sty;
		} else  if(sty>0 && !(sty -1 == dty && stx == dtx)) {
			rx = stx  ;
			ry = sty-1;
		}

	//alert('request pathcard:' + stx + '/' + sty +  '  rxy:' + rx  + '/' + ry );
		
	if (myPuzzle.columns[rx][ry] != null){
	//	alert('return ' + rx + '/' + ry);
		piece = myPuzzle.columns[rx][ry];	
	}
	
	return piece;
}

function getNextNormalPathCardLastTwo ( stx, sty, cx,cy, ex,ey ,dtx,dty){
	var mx = myPuzzle.xsize - 1;
	var my = myPuzzle.ysize - 1;
	var rx=0;
	var ry=0;
	var piece = null;
	if (isNearEmptyXY(stx,sty)){
//		alert('st (dest) near empty');
		return null;
	}
	//alert('request pathcard TWO LAST:' + stx + '/' + sty +  '  c:' + cx  + '/' + cy +  '  e:' + ex  + '/' + ey );

		if   (!(sty  == cy && stx+1 == cx) && !(sty  == dty && stx+1 == dtx) && !(sty  == cy && stx+1 == cx) && (stx < ex  ) && stx<mx )  {
			rx = stx + 1;
			ry = sty ;
		} else if   (!(sty  == cy && stx-1 == cx) && !(sty  == dty && stx-1 == dtx) && !(sty  == cy && stx-1 == cx) && (ex<=stx) && stx>0)  {
			rx = stx - 1;
			ry = sty ;

		} else	if   (!(sty + 1 == cy && stx == cx) && !(sty + 1 == dty && stx == dtx) && !(sty + 1 == cy && stx == cx) && (sty < ey  ) && sty<my)  {
			rx = stx ;
			ry = sty + 1;
//		} else 		if   (!(sty - 1 == cy && stx == cx) && !(sty - 1 == dty && stx == dtx) && (cy == ey  ) && sty>0 && (stx<=ex && cx<ex ) ) {
//			rx = stx ;
//			ry = sty - 1;
		} else  if   (!(sty - 1 == cy && stx == cx) && !(sty - 1 == dty && stx == dtx) && !(sty - 1 == cy && stx == cx)  && (sty > ey  ) && sty>0 )  {
			rx = stx;
			ry = sty-1;
			
		} else if   (!(sty  == cy && stx-1 == cx) && !(sty  == dty && stx-1 == dtx)  && !(sty  == cy && stx-1 == cx) && (stx > ex  ) && stx>0)  {
			rx = stx - 1;
			ry = sty;
		}else 		if   (!(sty + 1 == cy && stx == cx) && !(sty + 1 == dty && stx == dtx)  && sty<my)  {
			rx = stx ;
			ry = sty + 1;
		} else if   (!(sty  == cy && stx+1 == cx) && !(sty  == dty && stx+1 == dtx)    && stx<mx ){
			rx = stx + 1;
			ry = sty ;
		} else if   (!(sty  == cy && stx-1 == cx) && !(sty  == dty && stx-1 == dtx)   && stx>0)  {
			rx = stx - 1;
			ry = sty;
		} else if   (!(sty -1 == cy && stx == cx) && !(sty -1 == dty && stx == dtx)  && sty>0)  {
			rx = stx ;
			ry = sty-1;
		} else  if(stx<mx && !(sty  == dty && stx+1 == dtx)) {
			rx = stx + 1 ;
			ry = sty;
		} else  if(sty<my  && !(sty + 1 == dty && stx == dtx)) {
			rx = stx  ;
			ry = sty+1;
		} else  if(stx>0 && !(sty  == dty && stx-1 == dtx)) {
			rx = stx - 1 ;
			ry = sty;
		} else  if(sty>0 && !(sty -1 == dty && stx == dtx)) {
			rx = stx  ;
			ry = sty-1;
		}

	//alert('request pathcard:' + stx + '/' + sty +  '  rxy:' + rx  + '/' + ry );
		
	if (myPuzzle.columns[rx][ry] != null){
	//	alert('return ' + rx + '/' + ry);
		piece = myPuzzle.columns[rx][ry];	
	}
	
	return piece;
}

function addToBackShift(piece){
	var added = false;
	myPuzzle._dobackshift = false;
	if (myPuzzle._backshift!=null){
		var i = 0;
		var pc = null;
		for (i=0; i<myPuzzle._backshift.length && !added; i++){
			pc = myPuzzle._backshift[i];
			if (pc==null){
				myPuzzle._backshift[i] = piece;
				added = true;
			//	alert('added on pos ' + i);
			} 
		}
		
	}	
}

function backshiftLIFO(){
	var piece = null;
	var pcpos = -1;
	if (myPuzzle._backshift!=null){
		var i = 0;
		var pc = null;
		for (i=0; i<myPuzzle._backshift.length ; i++){
			pc = myPuzzle._backshift[i];
			if (pc!=null){
				piece = pc;
				pcpos = i;
			} 
		}
		
	}	
	if (pcpos>=0) myPuzzle._backshift[pcpos] = null;
	return piece;
}
function clearBackShift(){
	myPuzzle._dobackshift = false;
	if (myPuzzle._backshift!=null){
		for (i=0; i<myPuzzle._backshift.length; i++){
				myPuzzle._backshift[i] = null;
			} 
		
		
	}	

}

function inBackShift(x,y){
	var found = false;
	var end = false;
	if (myPuzzle._backshift!=null){
		var i = 0;
		var pc = null;
		for (i=0; i<myPuzzle._backshift.length && !end && !found; i++){
			pc = myPuzzle._backshift[i];
			if (pc!=null){
				if (pc._initx==x && pc._inity==y) found = true;
			} else end = true;
		}
		
	}	
	
	return found;
}

function backShiftIsEmpty(){
	var empty = true;

	if (myPuzzle._backshift!=null){
		var i = 0;
		var pc = null;
		for (i=0; i<myPuzzle._backshift.length && empty ; i++){
			pc = myPuzzle._backshift[i];
			if (pc!=null){
				empty=false;
			} 
		}
		
	}	
	
	return empty;
}

function backShiftCount(){
	var cnt = 0;

	if (myPuzzle._backshift!=null){
		var i = 0;
		var pc = null;
		for (i=0; i<myPuzzle._backshift.length ; i++){
			pc = myPuzzle._backshift[i];
			if (pc!=null){
				cnt++
			} 
		}
		
	}	
	
	return cnt;
}

function SortLastTwoRows(){
	var x = -1;
	var y = -1;
	var solvedx = -1;
	var solvedStop = false;	
	var stopFor = false; 
	var y1 = myPuzzle.ysize -2;
	var y2 = myPuzzle.ysize -1;
	
	var toppiece = null;
	var botpiece = null;
	var toppiecex = -1;
	var botpiecex = -1;
	var toppiecey = -1;
	var botpiecy = -1;
	
	for (x=0;x<myPuzzle.xsize && !stopFor;x++){
			if (myPuzzle.columns[x][y1]!=null && myPuzzle.columns[x][y2]!=null ){ 
					if (myPuzzle.columns[x][y1]._initx==x && myPuzzle.columns[x][y1]._inity==y1 && myPuzzle.columns[x][y2]._initx==x && myPuzzle.columns[x][y2]._inity==y2){
						//solved
						if (!solvedStop) solvedx = x;

					}else{
						//not solved
						solvedStop = true;
					}
			}else {
				solvedStop = true;
			}
			if (solvedStop && solvedx< myPuzzle.xsize-1){
				toppiece = getInitPiece(solvedx+1,y1);
				botpiece = getInitPiece(solvedx+1,y2);
			}

	}//END LOOP X
	
	var path = null;	
	var shiftpiece = null;
//	alert('botpiece=' + botpiece._currentx + '/' + botpiece._currenty);
	if (solvedx==myPuzzle.xsize-2 && isEmpty(myPuzzle.xsize-1,y1)){
		shiftpiece = getPiece(myPuzzle.xsize-1,y2);
	}else if (botpiece==null){
		//shiftpiece = getInitPiece( myPuzzle.xsize-1,y1);
	}else if (botpiece._currentx==solvedx+1){ //bottompiece in first col
			if (botpiece._currenty==y1){  //bottompiece in first row

	//			alert('botpiece._currenty==y1 ' + + toppiece._currentx + '/'+ toppiece._currenty);
			
				if ( toppiece._currenty == y1 && toppiece._currentx == solvedx+2 ){ //SLIDE IN
	//				alert ('toppiece shift down');
					path = shiftPieceTo(botpiece._currentx,y2,botpiece._currentx,botpiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,toppiece._currentx,toppiece._currenty);									
				} else if ( toppiece._currenty == y2 && toppiece._currentx == solvedx+2 && isEmpty(toppiece._currentx-1,toppiece._currenty )){
//					alert ('botpiece shift down');

					shiftpiece=botpiece;
				} else if ( toppiece._currenty == y2 && toppiece._currentx == solvedx+2 && isEmpty(toppiece._currentx,toppiece._currenty-1 )){
	//				alert ('toppiece shift up');
					shiftpiece=toppiece;
				} else	if ( toppiece._currenty == y2 && toppiece._currentx == solvedx+1 ){
	//				alert ('toppiece shift right');
					path = shiftPieceTo(toppiece._currentx+1,toppiece._currenty,toppiece._currentx,toppiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,toppiece._currentx+1,toppiece._currenty);
				} else {
	//				alert ('toppiece shiftPieceTo');
			
					if (toppiece._currenty == y2)
						path = shiftPieceTo(toppiece._currentx,y1,toppiece._currentx,toppiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,botpiece._currentx,botpiece._currenty);	
					else
						path = shiftPieceTo(toppiece._currentx-1,y1,toppiece._currentx,toppiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,botpiece._currentx,botpiece._currenty);	
				}

			} else {  //bottompiece in second row

				if ( toppiece._currenty == y1 && toppiece._currentx == solvedx+2 && isEmpty(toppiece._currentx-1,toppiece._currenty ) ){ //SLIDE IN
					shiftpiece=toppiece;
				} else if ( toppiece._currenty == y2 && toppiece._currentx == solvedx+2  ){ //SLIDE aside
					path = shiftPieceTo(toppiece._currentx+1,y2,toppiece._currentx,toppiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,botpiece._currentx,botpiece._currenty);	

				} else if ( toppiece._currenty == y2 && toppiece._currentx == solvedx+3  ){ //SLIDE aside >> up
					path = shiftPieceTo(botpiece._currentx,y1,botpiece._currentx,botpiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,toppiece._currentx,toppiece._currenty);	

				
				}else {
	
					if (botpiece._currenty == y2)
						path = shiftPieceTo(botpiece._currentx,y1,botpiece._currentx,botpiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,botpiece._currentx,botpiece._currenty);	
					else
						path = shiftPieceTo(botpiece._currentx-1,y1,botpiece._currentx,botpiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,botpiece._currentx,botpiece._currenty);	
				}
		}	
			///////////////////////////
	} else{ // MOVE BOTPIECE IN PLACE
		if (botpiece._currenty == y2)
			path = shiftPieceTo(botpiece._currentx,y1,botpiece._currentx,botpiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,botpiece._currentx,botpiece._currenty);	
		else
			path = shiftPieceTo(botpiece._currentx-1,y1,botpiece._currentx,botpiece._currenty,myPuzzle._emptyx,myPuzzle._emptyy,botpiece._currentx,botpiece._currenty);	
	}


	if (path!=null && shiftpiece!=null){
	//	alert('path and shiftpiece == null');
	}
	if (path!=null ){
		//	alert ('path found ' + path.length);
			var lastcard = null;
			var ci = 0;
			for (ci=0; ci<path.length; ci++){
				if (path[ci]!=null) lastcard = path[ci];
			}
			shiftpiece = lastcard;
	
	}
	
	
	if (shiftpiece!=null){
		if (isNearEmpty(shiftpiece)){
			swapWithEmpty(shiftpiece);
			slidePuzzlePieces();
		} else {
			//	alert('shift NOT OK: NOT NEAR EMPTY');
		}
		
	}

}

function SortLastTwoRows2(){

	if (lastTwoRowsShiftCheck()==false){
		var piece = null;
		if (myPuzzle._solveRotateCCW)
			piece = ccwRotateLastTwoRowsPiece();
		else
			piece = cwRotateLastTwoRowsPiece();
			
		if (isNearEmpty(piece)){
				//alert('shift OK');
			swapWithEmpty(piece);
			slidePuzzlePieces();
		} //else 			alert('LAST TWO ROW shift NOT OK: NOT NEAR EMPTY');
	} else {
		//	alert('shift OVER ROWS');
//			if (Math.random(2) * 10>5)
//				myPuzzle._solveRotateCCW = true;
//			else		
//				myPuzzle._solveRotateCCW = false;		

	var pt = null;
	var lastrow = true;
	for (x=0; x<myPuzzle.xsize && lastrow ;x++){
			pt = getPiece(x,myPuzzle.ysize-2);
			if (pt!=null){
			
				if (pt._initx==0 && pt._inity==myPuzzle.ysize-2) lastrow=false;
			} 
		}
			if (!lastrow)
				myPuzzle._solveRotateCCW = true;
			else		
				myPuzzle._solveRotateCCW = false;		
	
			swapWithEmpty(getSlidePieceLRT());
			slidePuzzlePieces();			
	
	
	}		

}
function lastTwoRowsShiftCheck(){
		var isOk = false;
		var x = 0;
		var y = 0;
		var mx = myPuzzle.xsize-1;
		var my = myPuzzle.ysize-1;
		var ex = myPuzzle._emptyx;
		var ey = myPuzzle._emptyy;
		var arr = new Array(myPuzzle.xsize*2);
		var arrorig = new Array(myPuzzle.xsize*2);
		
		var slpiece = getSlidePieceLRT();
		if (slpiece==null) return false;
		if (slpiece._initx==0 && slpiece._inity==my-1 ) return false;
		y = my-1;
		
		var chi= 0;
		var arri= 0;
		var chy= 0;
		var pt = null;
		for (x=0; x<=mx;x++){
			pt = getPiece(x,y);
			if (pt==null){
				arr[arri] = slpiece;
				chi = arri;
			} else if (samePiece(pt,slpiece)){
				arr[arri] = null;
			} else
				arr[arri] = pt;
			arrorig[arri] = pt;
	
			arri++;	
		}
		y = my;
		for (x=mx; x>=0;x--){
			pt = getPiece(x,y);
			if (pt==null){
				arr[arri] = slpiece;
				chi = arri;
			} else if (samePiece(pt,slpiece)){
				arr[arri] = null;
			} else
				arr[arri] = pt;
			arrorig[arri] = pt;
	
			arri++;
		}

		arr = sortPieceArray(arr);
		arrorig = sortPieceArray(arrorig);
		var gooddist =goodArrDistanse(slpiece);
		
		//count dist
		
				var checkend = false;
		var distcount = 0;
		var curdistcount = 1;
		var checkpc = null;
		
		isOk = true;
		var pcnotfound = true;
	//	alert('START ARRBUILD');
		for (x=1;x<arrorig.length && !checkend;x++){
			checkpc = arrorig[x];
			if (checkpc!=null){
				distcount = goodArrDistanse(checkpc);
				if (samePiece(checkpc,slpiece)){
					
					
						checkend=true;
						curdistcount++;
						pcnotfound = false;
				
				}else{
						curdistcount++;
					//	alert('piece not null');

					
				}
			
			} else {
				curdistcount++;
				//alert('piece IS null');
			}
		}
		if (pcnotfound) alert('piece not found!!');
		checkend = false;
		distcount = 0;
		var newdistcount = 1;
		checkpc = null;
		for (x=1;x<arr.length && !checkend;x++){
			checkpc = arr[x];
			if (checkpc!=null){
				distcount = goodArrDistanse(checkpc);
				if (samePiece(checkpc,slpiece)){
					
						isOk=true;
						newdistcount++;
						checkend = true;
					
				
				}else{
					
						newdistcount++;
					
				}
			
			} else {
				newdistcount++;
			}
		}
	//	alert(' good=' + gooddist + ' cur=' + curdistcount + ' new=' + newdistcount  )
		if (Math.abs(newdistcount-gooddist)<Math.abs(curdistcount-gooddist) )
		{
		debugAlert(' good=' + gooddist + ' cur=' + curdistcount + ' new=' + newdistcount  )

			isOk = true;
			
		}
		else 
			isOk = false;;
		return isOk;
}

function goodArrDistanse(piece){

		var gooddist = -1;
		var mx = myPuzzle.xsize-1;
		var my = myPuzzle.ysize-1;
		
		if (piece._inity==my-1){ // row my-1
			gooddist = piece._initx;
		
		}else if (piece._inity==my){ //last row
			gooddist = mx + 1  + (mx - piece._initx)  ;
		}

	return gooddist;
}

function sortPieceArray(arr){
	var fi = getPieceArrayIndex(arr,0,myPuzzle.ysize-2);
	var arrcp = new Array(arr.length);
	var i = 0;
	var j = 0;
	if (fi>0){ // SHIFT SO (0,ymax-1) is first
		for (i=fi;i<arr.length;i++){
			arrcp[j] = arr[i];
			j++;
		}
		for (i=0;i<fi;i++){
			arrcp[j] = arr[i];
			j++;
		}
	} else arrcp = arr;


	
	fi = getPieceArrayIndex(arrcp,-1,-1);
	//alert ('ep=' + fi);
	var mx = myPuzzle.xsize-1;
	if (fi<mx){ 
		for (i=fi;i<mx+1;i++){
			arrcp[i] = arrcp[i+1];
		}
		arrcp[mx+1] = null;
	}	else 	if (fi>mx+1){ 
		for (i=fi;i>mx+1;i--){
			arrcp[i] = arrcp[i-1];
		}
		arrcp[mx+1] = null;
	}	

	return arrcp;

}

function getPieceArrayIndex(arr,initx,inity){
	var i = 0;
	var maxi = arr.length - 1;
	var pc = null
//	alert( initx + '/' + inity);
	for (i=0; i<=maxi ; i++){
		pc = arr[i];
		if (pc==null && initx<0){
		//alert('pc is niull');
		 return i;
		 
		 }
		if (pc!=null){
			if (pc._initx == initx && pc._inity == inity){
		// 		alert('pc found');
			 	return i;
			}
		}
	
	}
	
	return -1;
}


function getSlidePieceLRT(){
		var x = 0;
		var y = 0;
		var mx = myPuzzle.xsize-1;
		var my = myPuzzle.ysize-1;
		var ex = myPuzzle._emptyx;
		var ey = myPuzzle._emptyy;
		
		if (ex==0 || ex==mx) return null;
		x = ex;
		if (ey==my){
			y = my-1
		}else
			y = my
		
		return getPiece(x,y);	
}

function samePiece(p1,p2){
	var b = false;
	if (p1==null && p2==null) return true;
	if (p1==null ) return false;
	if (p2==null) return false;
	
		if (p1._initx == p2._initx && p1._inity == p2._inity) b=true;
	//if (b) alert('samePiece x:' + p1._initx + '/' +  p2._initx + '   y:' +  p1._inity + '/' +  p2._inity);
	//else alert(' NOT samePiece x:' + p1._initx + '/' +  p2._initx + '   y:' +  p1._inity + '/' +  p2._inity);
	return b

}

function ccwRotateLastTwoRowsPiece(){
		var x = 0;
		var y = 0;
		var mx = myPuzzle.xsize-1;
		var my = myPuzzle.ysize-1;
		
		if (myPuzzle._emptyy == my){ //LAST ROW
			if (myPuzzle._emptyx == 0){ //FIRST COL
				x = 0;
				y = myPuzzle._emptyy-1;
			}else {
				x = myPuzzle._emptyx-1;
				y = myPuzzle._emptyy;
			}
		} else 		if (myPuzzle._emptyy == my-1){ //PRE LAST ROW
			if (myPuzzle._emptyx == mx){ //FIRST COL
				x = myPuzzle._emptyx;
				y = myPuzzle._emptyy+1;
			}else {
				x = myPuzzle._emptyx+1;
				y = myPuzzle._emptyy;
			}
		}
	
		return myPuzzle.columns[x][y];
}

function cwRotateLastTwoRowsPiece(){
		var x = 0;
		var y = 0;
		var mx = myPuzzle.xsize-1;
		var my = myPuzzle.ysize-1;
		
		if (myPuzzle._emptyy == my-1){ //LAST ROW
			if (myPuzzle._emptyx == 0){ //FIRST COL
				x = 0;
				y = my;
			}else {
				x = myPuzzle._emptyx-1;
				y = myPuzzle._emptyy;
			}
		} else 		if (myPuzzle._emptyy == my){ //PRE LAST ROW
			if (myPuzzle._emptyx == mx){ //FIRST COL
				x = mx;
				y = my-1;
			}else {
				x = myPuzzle._emptyx+1;
				y = myPuzzle._emptyy;
			}
		}
//		alert(x);
//		alert(y);
		return myPuzzle.columns[x][y];
}

function isSolved(){
	var solved = true
	for (y=0;y<myPuzzle.ysize && solved;y++){
		for (x=0;x<myPuzzle.xsize && solved;x++){
			if (myPuzzle.columns[x][y]!=null){ 
				if (myPuzzle.columns[x][y]._initx != myPuzzle.columns[x][y]._currentx) solved = false;
				if (myPuzzle.columns[x][y]._inity != myPuzzle.columns[x][y]._currenty) solved = false;
			}
		}
	}
	return solved;
}

function debugAlert(s){
	if (myPuzzle._xmydebug) alert(s);
}
function setDebug(b){
	myPuzzle._xmydebug = b;
}

function isEmpty(x,y){
	if (x==myPuzzle._emptyx && y==myPuzzle._emptyy) 
		return true;
	else
		return false;
}
function getInitPiece(x,y){

	var i = 0;
	var j = 0;
	var piece = null;
	for (i=0;i<myPuzzle.xsize;i++){
		for (j=0;j<myPuzzle.ysize;j++){
			piece = getPiece(i,j);
			if (piece!=null){
				if (piece._initx==x && piece._inity==y) return piece;
			}
		}
	}
	
	return null;
}
