// MFO Chess Diagrams Wizard 
// Written by buti-oxa for MFO (www.mrfixitonline.com) in 2003 - 2005
// (html part - www.mrfixitonline.com/readPosting.asp?PostingId=1406450)
// 
// Uses FEN-like format to code positions and highlights. 
// The format is: 
//		first field of FEN (rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR is starting position)
//		space
//		second field of FEN (w or b - whose turn to move)
//		space
//		size of the board to generate (s or b - small or big)
//		space
//		higlights (8/8/8/8/3b4/8/8/8 makes d4 blue)
//
// Good news is that Winboard can paste position in this format (ignoring all but the first 2 fields)

var whichEl = null;			// global position-tracking variables
var lastMouseX;				// global element-being-dragged variable
var lastMouseY;



var root;					// path to what's inside cd directory - set at init
var pixelTableTop = 0;		// board boundaries - constants made global for convinience only
var pixelTableLeft = 0;
var pixelTableRight = 0;
var pixelTableBottom = 0;
var pixelCellSize = 34;		// constant - for better readability only
var viewpoint = 'white';

var rgPiece;		// array that contains current piece on each of 64 squares of the board
var rgColor;		// array that contains current color of each of 64 squares of the board
var rgBgColor;		// array that contains 8 available background colors

//	Indexes for white view:
//	1  2  3  4  5  6  7  8 <- rank (y) = 1, files (x) from 1 to 8
//  9 10 11 12 13 14 15 16	(Ranks == Rows
// 17 ...

nHalfMovesInit = 1;			// default, can be changed by n= in URL

// undo arrays
var cUndo = 0;			// number of movements in the undo stack
var iUndo = 0;			// index (1-N) of the last displayed movement - the movement to undo
//				iUndo == 0 means nothing to undo, iUndo == cUndo means nothing to redo.

var rgUndoElementId = new Array();
var rgUndoOldFile = new Array();
var rgUndoOldRank = new Array();
var rgUndoOldColor = new Array();
var rgUndoNewFile = new Array();
var rgUndoNewRank = new Array();
var rgUndoNewColor = new Array();
var rgUndoLinkWithNext = new Array();
var rgUndoMoveType = new Array();		// 0N - normal 
										// 0C - coloring
										// 0S - setup (taking pieces off an on the board)
										// 1T - first (take away) part of a capture move
										// 2T - secong (move piece) part a capture move
										// 1C - first (king) move of a castling move
										// 2C - second (rook) move of castle
										// 1E - first (taking away) move of en passant
										// 2E - second (moving pawn) move of en passant



function DisplayHistory() {  

	var i = 0;
	var sHistory = '';
	var iHistory;
	var sMove;
	var sMoveNumber;
	var sSeparator;
	var fFirstMove = true;
	var fSkip;
	var fQueening;

	iHistory = parseInt(document.getElementById('startingmovenumber').value);
	
	if(isNaN(iHistory)) {iHistory = 0;} 

	if (iHistory > 0) {iHistory--;}

	for (i = 1; i <= cUndo; i++)
		{
		fQueening = false;
		
		if (rgUndoMoveType.length < cUndo)
			{
			// happens when you change iHistory, then click on the board
			// we get here "too late" when first half of the move is already recorded
			
			break;
			}
		
		if (rgUndoMoveType[i].charAt(0) == '1')
			{
			// first part of castling or capture - skip it

			fSkip = true;
			}
		else if (rgUndoMoveType[i] == '0C')
			{
			// Coloring pseudo-move - skip it
		
			fSkip = true;
			}
		else if (rgUndoMoveType[i] == '0S')
			{
			// setup - skip it
		
			fSkip = true;
			}
		else if (rgUndoMoveType[i] == '2C')
			{
			// castling
		
			fSkip = false;

			if (Math.abs(rgUndoNewFile[i] - rgUndoOldFile[i]) == 2)
				{
				sMove = 'O-O ';
				}
			else
				{
				sMove = 'O-O-O ';
				}
			}
		else 
			{
			// we do have normal move or second part of capture

			fSkip = false;

			if (rgUndoMoveType[i] == '2Q')
				{
				fQueening = true;
				
				sMove = GetPieceLetter4History(i);
				}
			else
				{
				if (rgUndoMoveType[i].charAt(1) == 'N')
					{
					sSeparator = '-';
					}
				else
					{
					// capture
					
					sSeparator = 'x';
					}
				
				sMove = GetPieceLetter4History(i) + 
					GetOldFile4History(i) + GetOldRank4History(i) + sSeparator +
					GetNewFile4History(i) + GetNewRank4History(i);
				}
			}

		if (!fSkip)
			{
			if (fQueening)
				{
				sMoveNumber = '';
				}
			else if (IsPieceColorWhite4History(i))
				{
				iHistory++;
				
				sMoveNumber = ' ' + iHistory + '. ';

				fFirstMove = false;
				}
			else
				{
				if (fFirstMove)
					{
					iHistory++;
					
					sMoveNumber = ' ' + iHistory + '. ... ';
					}
				else
					{
					sMoveNumber = ' ';
					}
				
				fFirstMove = false;
				}

			sHistory += sMoveNumber + sMove;
			}
    }

	document.getElementById('historystring').value = sHistory;
}


function IsPieceColorWhite4History(i) {  

	var moving_piece_color = rgUndoElementId[i].substr(5,1);

	if (moving_piece_color == 'w') {return true;}

	return false;
}

function GetPieceLetter4History(i) {  

	var moving_piece = rgUndoElementId[i].substr(7,1);
	moving_piece = moving_piece.toUpperCase();

	if (moving_piece == 'P') {moving_piece = '';}

	return moving_piece;

}

function GetOldFile4History(i) {return GetFile4History(rgUndoOldFile[i]);}
function GetNewFile4History(i) {return GetFile4History(rgUndoNewFile[i]);}


function GetFile4History(undo_file) {  

	var charFile;

	if (viewpoint == 'white')
		{
		charFile = String.fromCharCode(96 + undo_file);
		}
	else
		{
		charFile = String.fromCharCode(96 + 9 - undo_file);
		}
	
	return charFile;
}

function GetOldRank4History(i) {return GetRank4History(rgUndoOldRank[i]);}
function GetNewRank4History(i) {return GetRank4History(rgUndoNewRank[i]);}


function GetRank4History(file) {  

	if (viewpoint == 'white')
		{
		return 9-file;
		}
	return file;
}

function UndoOneMove() {  

	if (iUndo == 0) return;

	UndoOneMovement(iUndo);

	// check if it is a two-part move

	if (rgUndoMoveType[iUndo].charAt(0) != '0')
		{
		iUndo--;
		UndoOneMovement(iUndo);
		}

	// check if is queening

	if (rgUndoMoveType[iUndo].charAt(1) == 'Q')
		{
		// Assert(iUndo > 2)
		
		iUndo--;
		UndoOneMovement(iUndo);

		// check if it is a two-part move
		
		if (rgUndoMoveType[iUndo].charAt(0) != '0')
			{
			iUndo--;
			UndoOneMovement(iUndo);
			}
		}

	iUndo--;

	toggleActiveColor();
}

function RedoOneMove() {  

	if (iUndo == cUndo) 
		{
		return;
		}

	iUndo++; 
	
	RedoOneMovement(iUndo);

	// check if it is a two-part move

	if (rgUndoMoveType[iUndo].charAt(0) != '0')
		{
		// assert(iUndo < cUndo); 
		
		iUndo++;
		RedoOneMovement(iUndo);
		}

	// check if queening follows

	if (iUndo < cUndo && rgUndoMoveType[iUndo+1].charAt(1) == 'Q')
		{
		// assert(iUndo < cUndo); 
		
		iUndo++;
		RedoOneMovement(iUndo);
		
		// assert(iUndo < cUndo); 
		
		iUndo++;
		RedoOneMovement(iUndo);
		}

	toggleActiveColor();
}

function UndoOneMovement(iUndo) { 

	var el;

	if (rgUndoElementId[iUndo].substr(5,1) == 'c')		// undo color
		{
		setSquareColor(rgUndoNewFile[iUndo], rgUndoNewRank[iUndo], rgUndoOldColor[iUndo]);

		rgColor[getIndexGivenFileRank(rgUndoNewFile[iUndo], rgUndoNewRank[iUndo])] = 
																rgUndoOldColor[iUndo];
		return;
		}

	if (rgUndoNewFile[iUndo] != 0)
		{
		takePieceOffVirtualBoardGivenIndices(rgUndoNewFile[iUndo], rgUndoNewRank[iUndo]);
		}

	if (rgUndoOldFile[iUndo] == 0)
		{
		resetMovingPiece(rgUndoElementId[iUndo].substr(5));
		}
	else
		{
		putPieceOnVirtualBoardGivenIndices(rgUndoOldFile[iUndo], rgUndoOldRank[iUndo], rgUndoElementId[iUndo]);
		
		el = document.getElementById(rgUndoElementId[iUndo]);

		pixelLeft = pixelTableLeft + (rgUndoOldFile[iUndo]-1) * pixelCellSize + 1;
		pixelTop = pixelTableTop + (rgUndoOldRank[iUndo]-1) * pixelCellSize + 1;
		
		el.style.left = pixelLeft + "px";
		el.style.top = pixelTop + "px";
		}
}

function RedoOneMovement(iUndo) {  

	var el;

	if (rgUndoElementId[iUndo].substr(5,1) == 'c')		// redo color
		{
		setSquareColor(rgUndoNewFile[iUndo], rgUndoNewRank[iUndo], rgUndoNewColor[iUndo]);

		rgColor[getIndexGivenFileRank(rgUndoNewFile[iUndo], rgUndoNewRank[iUndo])] = 
																rgUndoNewColor[iUndo];
		return;
		}

	if (rgUndoOldFile[iUndo] != 0)
		{
		takePieceOffVirtualBoardGivenIndices(rgUndoOldFile[iUndo], rgUndoOldRank[iUndo]);
		}

	if (rgUndoNewFile[iUndo] == 0)
		{
		resetMovingPiece(rgUndoElementId[iUndo].substr(5));
		}
	else
		{
		putPieceOnVirtualBoardGivenIndices(rgUndoNewFile[iUndo], rgUndoNewRank[iUndo], rgUndoElementId[iUndo]);
		
		el = document.getElementById(rgUndoElementId[iUndo]);

		pixelLeft = pixelTableLeft + (rgUndoNewFile[iUndo]-1) * pixelCellSize + 1;
		pixelTop = pixelTableTop + (rgUndoNewRank[iUndo]-1) * pixelCellSize + 1;
		
		el.style.left = pixelLeft + "px";
		el.style.top = pixelTop + "px";
		}
}

function takePieceOffVirtualBoardGivenGeometry(pixelLeft, pixelTop) {  
	
	takePieceOffVirtualBoardGivenIndices(xFromLeft(pixelLeft), yFromTop(pixelTop));
}

function takePieceOffVirtualBoardGivenIndices(x, y) {  
	
	rgPiece[getIndexGivenFileRank(x, y)] = "x_x";
}

function putPieceOnVirtualBoardGivenGeometry(pixelLeft, pixelTop, idEl) {  

	putPieceOnVirtualBoardGivenIndices(xFromLeft(pixelLeft), yFromTop(pixelTop), idEl);
}

function putPieceOnVirtualBoardGivenIndices(x, y, idEl) {  
	
	rgPiece[getIndexGivenFileRank(x, y)] = idEl.substr(5);
}

function xFromLeft(pixelLeft) {  
	
	return Math.floor((pixelLeft - pixelTableLeft + 16) / pixelCellSize) + 1;
}

function yFromTop(pixelTop) {  
	
	return Math.floor((pixelTop - pixelTableTop + 16) / pixelCellSize) + 1;
}

function getIndexGivenFileRank(x, y) {  
	if (viewpoint == 'white')
		{
		return 8 * (y-1) + x;
		}
	else
		{
		return 8 * (8-y) + 9-x;
		}
}

function getFileGivenIndex(i) {  
	if (viewpoint == 'white')
		{
		return Math.floor((i-1)/8) + 1;
		}
	else
		{
		return 8 - Math.floor((i-1)/8);
		}
}

function getRankGivenIndex(i) {  
	if (viewpoint == 'white')
		{
		return 1 + (i-1)%8;
		}
	else
		{
		return 8 - (i-1)%8;
		}
}

function getCellGivenIndex(i) {  
	var elTable = document.getElementById('board');
	var elRow = elTable.rows[getFileGivenIndex(i)+1];
	var elCell = elRow.cells[getRankGivenIndex(i)];
	return elCell;
}

// Grab bucket or piece (on mousedown)

function grabEl(e) {       

	if (!e) var e = window.event;				// Mozilla or IE

	if (e.target) whichEl = e.target;			// W3C
	else whichEl = e.srcElement;				// IE

    while (whichEl.id.indexOf("drag") == -1) {
        whichEl = whichEl.parentElement;
        if (whichEl == null) { return }
    }

	document.onmousemove = moveEl;
	document.onmouseup = dropEl;

	lastMouseX	= e.clientX;
	lastMouseY	= e.clientY;

	// start recording new move
	
	iUndo++;
	cUndo = iUndo;
	rgUndoElementId[iUndo] = whichEl.id;

	pixelTop = DL_GetElementTop(whichEl);
	pixelLeft = DL_GetElementLeft(whichEl);

	if (fWithinBoard(pixelLeft, pixelTop))
		{
		takePieceOffVirtualBoardGivenGeometry(pixelLeft, pixelTop);		

		rgUndoOldFile[iUndo] = xFromLeft(pixelLeft);
		rgUndoOldRank[iUndo] = yFromTop(pixelTop);
		}
	else
		{
		rgUndoOldFile[iUndo] = 0;
		rgUndoOldRank[iUndo] = 0;
		}
	return false;
}

// move bucket or piece (with mouse) if grabbed (whichEl != null))

function moveEl(e) {  
    if (whichEl == null) { return };

	if (!e) var e = window.event;

	var ey	= e.clientY;
	var ex	= e.clientX;
	var y = parseInt(whichEl.style.top );
	var x = parseInt(whichEl.style.left);
	var nx, ny;

	nx = x + ex - lastMouseX;
	ny = y + ey - lastMouseY;

	whichEl.style["left"] = nx + "px";
	whichEl.style["top" ] = ny + "px";
	lastMouseX	= ex;
	lastMouseY	= ey;

	return false;
}

// Drop bucket or piece (on mouseup)

function dropEl(e) {      
    if (whichEl == null) { return };

	if (!e) var e = window.event;
	
	document.onmousemove = null;
	document.onmouseup = null;

	idEl = whichEl.id;
    pixelLeft = parseInt(whichEl.style.left, 10);
    pixelTop = parseInt(whichEl.style.top, 10);

	if (!fWithinBoard(pixelLeft, pixelTop))
		{
		resetMovingPiece(idEl.substr(5));

		if (rgUndoOldFile[iUndo] == 0)
			{
			// empty move - don't record
			iUndo--;
			}
		else
			{
			rgUndoNewFile[iUndo] = 0;
			rgUndoNewRank[iUndo] = 0;
			rgUndoMoveType[iUndo] = '0S';
			}
		
	    whichEl = null;
		return;
		}

	x = xFromLeft(pixelLeft);
	y = yFromTop(pixelTop);

	rgUndoNewFile[iUndo] = x;
	rgUndoNewRank[iUndo] = y;

	i = getIndexGivenFileRank(x, y);

	if (idEl.substr(5,1) == 'c')
		{
		rgUndoMoveType[iUndo] = '0C';				// coloring move
		rgUndoOldColor[iUndo] = rgColor[i];
		rgUndoNewColor[iUndo] = idEl.substr(7,1);
		
		rgColor[i] = idEl.substr(7,1);
		
		setSquareColor(x, y, rgColor[i]);
		
		resetMovingPiece(idEl.substr(5));
		
	    whichEl = null;
		return;
		}

	fDontCount = false;

	if (rgPiece[i] != "x_x")
		{
		// it is a capture - take the old piece off the board
		
		resetMovingPiece(rgPiece[i]);

		// record take away second movement BEFORE the main move

		if (rgUndoOldFile[iUndo] != 0)
			{
			// one piece takes another 

			move_type_1 = '1T';
			move_type_2 = '2T';
			}
		else
			{
			if (rgPiece[i].substr(2,1) == 'p' && (y == 1 || y == 8))
				{
				// pawn transformation (queening)
				
				move_type_1 = '1Q';
				move_type_2 = '2Q';
				
				fDontCount = true;
				}
			else
				{
				move_type_1 = '0S';
				move_type_2 = '0S';
				}
			}

		rgUndoMoveType[iUndo+1] = move_type_2;
		rgUndoElementId[iUndo+1] = rgUndoElementId[iUndo];
		rgUndoOldFile[iUndo+1] = rgUndoOldFile[iUndo];
		rgUndoOldRank[iUndo+1] = rgUndoOldRank[iUndo];
		rgUndoNewFile[iUndo+1] = rgUndoNewFile[iUndo];
		rgUndoNewRank[iUndo+1] = rgUndoNewRank[iUndo];

		rgUndoMoveType[iUndo] = move_type_1;
		rgUndoElementId[iUndo] = 'drag_' + rgPiece[i];
		rgUndoOldFile[iUndo] = x;
		rgUndoOldRank[iUndo] = y;
		rgUndoNewFile[iUndo] = 0;
		rgUndoNewRank[iUndo] = 0;
		
		iUndo++;
		}
	else
		{
		if (rgUndoOldFile[iUndo] == 0)
			{
			rgUndoMoveType[iUndo] = '0S';		// setup move
			}
		else
			{
			if (rgUndoNewFile[iUndo] == rgUndoOldFile[iUndo] &&
				rgUndoNewRank[iUndo] == rgUndoOldRank[iUndo])
				{
				// empty move - don't record
				iUndo--;
				fDontCount = true;
				}
			else
				{
				rgUndoMoveType[iUndo] = '0N';		// normal move
				}
			}
		}

	if (Is_Enpassant(x, y))
		{
		// took enemy pawn off the board

		var rankEnemyPawn = rgUndoNewRank[iUndo-1];
		var fileEnemyPawn = rgUndoNewFile[iUndo-1];
		var iEnemyPawn = getIndexGivenFileRank(fileEnemyPawn, rankEnemyPawn);
		var idEnemyPawn = rgPiece[iEnemyPawn];
		
		// take the pawn off the board
		
		resetMovingPiece(idEnemyPawn);

		// take the pawn off the virtual board
		
		takePieceOffVirtualBoardGivenIndices(fileEnemyPawn, rankEnemyPawn);
		
		// record take the movements

		rgUndoMoveType[iUndo+1] = '2E';
		rgUndoElementId[iUndo+1] = rgUndoElementId[iUndo];
		rgUndoOldFile[iUndo+1] = rgUndoOldFile[iUndo];
		rgUndoOldRank[iUndo+1] = rgUndoOldRank[iUndo];
		rgUndoNewFile[iUndo+1] = rgUndoNewFile[iUndo];
		rgUndoNewRank[iUndo+1] = rgUndoNewRank[iUndo];

		rgUndoMoveType[iUndo] = '1E';
		rgUndoElementId[iUndo] = 'drag_' + idEnemyPawn;
		rgUndoOldFile[iUndo] = fileEnemyPawn;
		rgUndoOldRank[iUndo] = rankEnemyPawn;
		rgUndoNewFile[iUndo] = 0;
		rgUndoNewRank[iUndo] = 0;
		
		iUndo++;
		}

	if (Is_Castling(x, y))
		{
		king_starting_rank = rgUndoOldFile[iUndo];
		king_ending_rank = x;
		
		if (king_ending_rank > king_starting_rank)
			{
			// castling to to right
			
			rook_starting_rank = 8;
			rook_ending_rank = king_ending_rank - 1;
			}
		else
			{
			// castling to to left
			
			rook_starting_rank = 1;
			rook_ending_rank = king_ending_rank + 1;
			}

		idRook = rgPiece[getIndexGivenFileRank(rook_starting_rank, y)];
		
		takePieceOffVirtualBoardGivenIndices(rook_starting_rank, y);

		putPieceOnVirtualBoardGivenIndices(rook_ending_rank, y, 'drag_' + idRook);

		// move the rook
		
		var el = document.getElementById('drag_' + idRook);
		el.style.left = (pixelTableLeft + (rook_ending_rank - 1) * pixelCellSize + 1) + "px";

		rgUndoMoveType[iUndo] = '1C';
		rgUndoElementId[iUndo] = rgUndoElementId[iUndo];
		rgUndoOldFile[iUndo] = rgUndoOldFile[iUndo];
		rgUndoOldRank[iUndo] = rgUndoOldRank[iUndo];
		rgUndoNewFile[iUndo] = rgUndoNewFile[iUndo];
		rgUndoNewRank[iUndo] = rgUndoNewRank[iUndo];

		iUndo++;
		
		rgUndoMoveType[iUndo] = '2C';
		rgUndoElementId[iUndo] = 'drag_' + idRook;
		rgUndoOldFile[iUndo] = rook_starting_rank;
		rgUndoOldRank[iUndo] = y;
		rgUndoNewFile[iUndo] = rook_ending_rank;
		rgUndoNewRank[iUndo] = y;
		}


	cUndo = iUndo;
	
	putPieceOnVirtualBoardGivenGeometry(pixelLeft, pixelTop, idEl);

	// center the piece in the square

	pixelLeft = pixelTableLeft + (x-1) * pixelCellSize + 1;
	pixelTop = pixelTableTop + (y-1) * pixelCellSize + 1;
	
    whichEl.style.left = pixelLeft + "px";
    whichEl.style.top = pixelTop + "px";
	
    whichEl = null;

	DisplayHistory();

	if (!fDontCount)
		{
		toggleActiveColor();
		}
}


function Is_White2Move()
{
	if (document.boarddiagram.active_color[1].checked)
		{
		return true;
		}
	
	return false;
}

function toggleActiveColor()
{
	if (document.boarddiagram.active_color[1].checked)
		{
		document.boarddiagram.active_color[0].checked = true;
		}
	else
		{
		document.boarddiagram.active_color[1].checked = true;
		}
	
	return;
}

function Is_Castling(x, y)
	{
	var moving_piece;
	var needed_rook;
	var starting_rank;
	var starting_file;

	if (iUndo == 0) return false;
	
	moving_piece = rgUndoElementId[iUndo].substr(5,3);
	
	if (moving_piece == "w_k")
		{
		needed_rook = "w_r";
		
		if (viewpoint == 'white')
			{
			starting_rank = 8;
			starting_file = 5;
			}
		else
			{
			starting_rank = 1;
			starting_file = 4;
			}
		}
	else if (moving_piece == "b_k")
		{
		needed_rook = "b_r";
		
		if (viewpoint == 'white')
			{
			starting_rank = 1;
			starting_file = 5;
			}
		else
			{
			starting_rank = 8;
			starting_file = 4;
			}
		}
	else
		{
		return false;					// not a king moving - not a castling
		}
	
	
	if (rgUndoOldFile[iUndo] != starting_file)
		{
		return false;					// king not in starting position - not a castling		
		}
	
	if (rgUndoOldRank[iUndo] != starting_rank)
		{
		return false;					// king not in starting position - not a castling		
		}
	
	if (y != rgUndoOldRank[iUndo])
		{
		return false;					// king did not stay in the same rank - not a castling		
		}
	
	if (x != rgUndoOldFile[iUndo]+2 && x != rgUndoOldFile[iUndo]-2)
		{
		return false;					// king did not move by exactly two squares - not a castling		
		}

	if (x > rgUndoOldFile[iUndo]) 
		{
		// castling to the right - first check that the rook is there

		if (rgPiece[getIndexGivenFileRank(8, y)].substr(0,3) != needed_rook)
			{
			return false;
			}

		// check that there is nothing between the rook and the king
		
		for (xx = rgUndoOldFile[iUndo] + 1; xx < 8; xx++) {
			if (rgPiece[getIndexGivenFileRank(xx, y)] != "x_x")
				{
				return false;
				}
			}

		return true;
		}
		
	if (x < rgUndoOldFile[iUndo])
		{
		// castling to the left - first check that the rook is there

		if (rgPiece[getIndexGivenFileRank(1, y)].substr(0,3) != needed_rook)
			{
			return false;
			}

		// check that there is nothing between the rook and the king
		
		for (xx = 2; xx < rgUndoOldFile[iUndo]; xx++) {
			if (rgPiece[getIndexGivenFileRank(xx, y)] != "x_x")
				{
				return false;
				}
			}
		
		return true;
		}

	return false;
}

function Is_Enpassant(x, y)
{
	var moving_piece;
	var starting_rank;
	var ending_rank;
	var starting_rank_prev_move;
	var ending_rank_prev_move;
	var enemy_piece;

	if (iUndo < 2) return false;		// need at least 1 move of history
	
	moving_piece = rgUndoElementId[iUndo].substr(5,3);
	
	if (moving_piece == "w_p")
		{
		enemy_piece = "b_p";
			
		if (viewpoint == 'white')
			{
			starting_rank = 4;
			ending_rank = 3;
			starting_rank_prev_move = 2;
			ending_rank_prev_move = 4;
			}
		else
			{
			starting_rank = 5;
			ending_rank = 6;
			starting_rank_prev_move = 7;
			ending_rank_prev_move = 5;
			}
		}
	else if (moving_piece == "b_p")
		{
		enemy_piece = "w_p";

		if (viewpoint == 'white')
			{
			starting_rank = 5;
			ending_rank = 6;
			starting_rank_prev_move = 7;
			ending_rank_prev_move = 5;
			}
		else
			{
			starting_rank = 4;
			ending_rank = 3;
			starting_rank_prev_move = 2;
			ending_rank_prev_move = 4;
			}
		}
	else
		{
		return false;					// not a pawn moving
		}
	
	// Check if the pawn move is a way consistent with en passant
	
	if (rgUndoOldRank[iUndo] != starting_rank)
		{
		return false;					// pawn does not start in correct rank
		}
	
	if (y != ending_rank)
		{
		return false;					// pawn does not end in correct rank
		}
	
	if (x != rgUndoOldFile[iUndo]+1 && x != rgUndoOldFile[iUndo]-1)
		{
		return false;					// pawn should move left or right by 1		
		}

	// Check if there is enemy pawn that moved last time in an appropriate way
	
	if (rgUndoElementId[iUndo-1].substr(5,3) != enemy_piece)
		{
		return false;					// last move not by a pawn of opposite color
		}

	if (rgUndoOldRank[iUndo-1] != starting_rank_prev_move)
		{
		return false;					// pawn did not start in correct rank
		}

	if (rgUndoNewRank[iUndo-1] != ending_rank_prev_move)
		{
		return false;					// pawn did not end in correct rank
		}

	if (rgUndoOldFile[iUndo-1] != x)
		{
		return false;					// pawn did not start in correct file
		}

	if (rgUndoNewFile[iUndo-1] != x)
		{
		return false;					// pawn didn ot end in correct file
		}

	return true;
}
	


// duplicated in mfochess.js

function DL_GetElementLeft(eElement)
{
    var nLeftPos = eElement.offsetLeft;          // initialize var to store calculations
    var eParElement = eElement.offsetParent;     // identify first offset parent element  
    while (eParElement != null)
    {                                            // move up through element hierarchy
        nLeftPos += eParElement.offsetLeft;      // appending left offset of each parent
        eParElement = eParElement.offsetParent;  // until no more offset parents exist
    }
    return nLeftPos;                             // return the number calculated
}

// duplicated in mfochess.js

function DL_GetElementTop(eElement)
{
    var nTopPos = eElement.offsetTop;            // initialize var to store calculations
    var eParElement = eElement.offsetParent;     // identify first offset parent element  
    while (eParElement != null)
    {                                            // move up through element hierarchy
        nTopPos += eParElement.offsetTop;        // appending top offset of each parent
        eParElement = eParElement.offsetParent;  // until no more offset parents exist
    }
    return nTopPos;                              // return the number calculated
}

function setupBoardFromUrl() {

	// null string means take if from current URL
	// root is empty - we are in the same directory

	setupBoard(null, '');
}

// used by the editor, first parameter is the src of the diagram pseudo-image

function setupBoard(strQuery, root) {

	var q = new Query(strQuery);

	initDiagramBuilder(root);
	
	// Produce position description old MFO style. FEN string comes first
	
	var sMFOFEN = q.get("f");
	
	if (sMFOFEN == null) { return; } 					// no FEN - empty board

	// whose move comes next - Move is m=B or m=W

	var move = q.get("m");
	sMFOFEN += (move == null || move.toUpperCase() != 'B') ? ' w' : ' b'

	// then size of the board - Size is Large or Small

	var size = q.get("s");
	sMFOFEN += (size  == null || size .toUpperCase() != 'L') ? ' S' : ' L'

	// and finally, highlight colors if present

	var colors = q.get("c");
	sMFOFEN += (colors == null) ? '' : ' ' + colors;
	
	loadboardNewFormat(sMFOFEN);

	// how handle move number if set

	var cHalfMoves = q.get("n");
	if (cHalfMoves == null) { return; } 		// no number - done

	nHalfMovesInit = parseInt(cHalfMoves);
	var cMoves = 1 + Math.floor(nHalfMovesInit/2);
	
	document.getElementById('startingmovenumber').value = cMoves;

	// move number resets who2move correctly - do we still need that one on new MFO?
	
	if (cHalfMoves % 2 == 0) document.boarddiagram.active_color[1].checked = true;
	else document.boarddiagram.active_color[0].checked = true;
}

// restore position from input string given by parameter or clipboard

function loadboarddata(boardIn) {

	var board;
	var el;

	if (boardIn != undefined)
		{
		board = boardIn;
		}
	else if (document.getElementById('boardstring').value != "")
		{
		board = document.getElementById('boardstring').value;
		}
	else
		{
		if (window.clipboardData)
			{
			// Firefox cannot do that, and hates when we try.
			
			board = window.clipboardData.getData("Text");

			if (board == null) board = '';
			
			// sClipboard = window.clipboardData.getData("Text");
			// aClipboard = sClipboard.split("\r\n");
			// board = aClipboard[0];
			}
		}

	// setting initial position by inputting S# id

	if (board.match(/S#\d+/)) 
		{
		var re = new RegExp('S#(\\d+)');		
		var match = re.exec(board); 			
 		var strFen = generate960FenLine(match[1]);

		board = strFen.toLowerCase() + 
					'/pppppppp/8/8/8/8/PPPPPPPP/' +
					strFen + ' w ';
		}
	
	// check for new Fen-like format first

	if (!loadboardNewFormat(board))
		{
		// now, it is something different, clean after this attempt and try Pgn format

		var game;

		resetBoard();
		
		game = Pgn2MfoTranslate(board);

		boardFen = game.fen;
		
		if (boardFen == "")
			{
			// not it is not pgn either, old mfo format is our last hope

			loadboardOldFormat(board);
			}
		else
			{
			loadboardNewFormat(boardFen);
			}
		}

	cUndo = 0;
	iUndo = 0;
	nHalfMovesInit = 1;
	DisplayHistory();
}
	 	
	 	
function loadboardNewFormat(strBoard) {

	var rgSplit1;
	var rgSplit2;
	var	sFile, sCode, sPiece, sColor;
	var i, k, x, y;
	var sPieces = "rnbqkp";
	var sColors = "prb";
	var freePiece = new Array();

	resetBoard();

	// strBoard in new format starts with 8 pieces separated by /. Check for that.

	rgSplit1 = strBoard.split(" ");

	rgSplit2 = rgSplit1[0].split('/');

	if (rgSplit2.length != 8) return false;

	for (y = 1; y < 9; y++) 
		{
		x = 1;
		sFile = rgSplit2[y-1];

		for (k = 0; k < sFile.length; k++)
			{
			if (x > 8) return false;
			
			sCode = sFile.charAt(k);

			if (isNaN(parseInt(sCode))) 
				{
				sPiece = sCode.toLowerCase();

				if (sPieces.indexOf(sPiece) == -1) return false;

				sColor = (sPiece == sCode) ? 'b': 'w';
				
				if (freePiece[sColor+sPiece] == undefined) {
					freePiece[sColor+sPiece] = 1;
					}

				if (freePiece[sColor+sPiece] > 8) return false;
				
				i = 8 * (y-1) + x;
				
				rgPiece[i] = sColor + '_' + sPiece + '_' + freePiece[sColor+sPiece];

				freePiece[sColor+sPiece]++;

				el = document.getElementById('drag_' + rgPiece[i]);

				el.style.top = (pixelTableTop + (getFileGivenIndex(i)-1) * pixelCellSize + 1) + "px";
				el.style.left = (pixelTableLeft + (getRankGivenIndex(i)-1) * pixelCellSize + 1) + "px";
				
				x++;
				}
			else 
				{
				x += parseInt(sCode);
				}
			}
	}

	// whose move is next

	if (rgSplit1[1] == 'w')
		{
		document.boarddiagram.active_color[1].checked = true;
		}
	else
		{
		document.boarddiagram.active_color[0].checked = true;
		}
	
	// big or small diagram
	
	if (rgSplit1[2] == 'L')
		{
		document.boarddiagram.board_size[0].checked = true;
		}
	else
		{
		document.boarddiagram.board_size[1].checked = true;
		}
	
	// do highlights if present

	if (rgSplit1.length < 4) return true;
	
	rgSplit2 = rgSplit1[3].split('/');

	if (rgSplit2.length != 8) return true;
	
	for (y = 1; y < 9; y++) 
		{
		x = 1;
		sFile = rgSplit2[y-1];

		for (k = 0; k < sFile.length; k++)
			{
			if (x > 8) return true;
			
			sCode = sFile.charAt(k);

			if (isNaN(parseInt(sCode))) 
				{
				sColor = sCode.toLowerCase();

				if (sColors.indexOf(sColor) == -1) return true;

				i = 8 * (y-1) + x;
				
				rgColor[i] = sColor;
				
				elCell = getCellGivenIndex(i);
				elCell.style.background = getBGColor(x, y, sColor);
				
				x++;
				}
			else 
				{
				x += parseInt(sCode);
				}
			}
	}

	return true;
}

function loadboardOldFormat(board) {

	var freePiece = new Array();
	
	resetBoard();

	if (board.length != 260) { board = 's...' + board; }

	if (board.length != 260) {
		alert('Incorrect board');
		return;
	} 

	if (board.substr(0,1) == 'b')	
		{
		document.boarddiagram.board_size[0].checked = true;
		}
	else
		{
		document.boarddiagram.board_size[1].checked = true;
		}

	for (y = 1; y < 9; y++) {
		for (x = 1; x < 9; x++) {
			i = 8 * (y-1) + x;
			
			p_space = board.substr(i*4, 4);
			color = p_space.substr(0,1);
			file = p_space.substr(1,1);
			c_highlight = p_space.substr(2,1);

			if (file != 'x')
				{
				if (freePiece[color+file] == undefined) {
					freePiece[color+file] = 1;
					}
				
				rgPiece[i] = color + '_' + file + '_' + freePiece[color+file];

				freePiece[color+file]++;

				el = document.getElementById('drag_' + rgPiece[i]);

				el.style.top = (pixelTableTop + (getFileGivenIndex(i)-1) * pixelCellSize + 1) + "px";
				el.style.left = (pixelTableLeft + (getRankGivenIndex(i)-1) * pixelCellSize + 1) + "px";
				}

			rgColor[i] = c_highlight;
			
			if (c_highlight != 'x')
				{
				elCell = getCellGivenIndex(i);
				elCell.style.background = getBGColor(x, y, c_highlight);
				}
		}
	}
}


function createboarddataCore() {
	
	var i, piece, color;
	var board = new Object;

	// pieces

	boarddata = '';
	for (i = 1; i < 65; i++)
		{
		if (i > 1 && i%8 == 1) boarddata += '/';
		
		piece = rgPiece[i].substr(2,1);
		color = rgPiece[i].substr(0,1);

		if (piece[1] != 'x' && color == 'w') piece = piece.toUpperCase();

		boarddata += piece;
		}

	board.fen = replaceXX(boarddata);

	// whose move

	if (document.boarddiagram.active_color[1].checked)
		{
		board.move = "w";
		}
	else
		{
		board.move = "b";
		}
	
	// big or small diagram
	
	if (document.boarddiagram.board_size[0].checked)
		{
		board.size = 'L';
		}
	else
		{
		board.size = 'S';
		}

	// colors

	boarddata = '';
	for (i = 1; i < 65; i++)
		{
		if (i > 1 && i%8 == 1) boarddata += '/';
		
		boarddata += rgColor[i];
		}
	
	board.colors = replaceXX(boarddata);

	return board;
}

function replaceXX(boarddata) {

	boarddata = boarddata.replace(/xxxxxxxx/g,'8');
	boarddata = boarddata.replace(/xxxxxxx/g,'7');
	boarddata = boarddata.replace(/xxxxxx/g,'6');
	boarddata = boarddata.replace(/xxxxx/g,'5');
	boarddata = boarddata.replace(/xxxx/g,'4');
	boarddata = boarddata.replace(/xxx/g,'3');
	boarddata = boarddata.replace(/xx/g,'2');
	boarddata = boarddata.replace(/x/g,'1');
	boarddata = boarddata.replace('8/8/8/8/8/8/8/8','');
	
	return boarddata;
}

function loadstartboard() {
	var boarddata = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w ';
	
	if (document.boarddiagram.board_size[0].checked)
		{
		boarddata += 'b ';
		}
	else
		{
		boarddata += 's ';
		}

 loadboarddata(boarddata);
 document.getElementById('boardstring').value = ''; 
 document.getElementById('startingmovenumber').value = 1;
}

function loadblankboard() {
	var boarddata = '8/8/8/8/8/8/8/8 w ';
	
	if (document.boarddiagram.board_size[0].checked)
		{
		boarddata += 'L ';
		}
	else
		{
		boarddata += 'S ';
		}

 loadboarddata(boarddata);
 document.getElementById('boardstring').value = '';
}

function fWithinBoard(pixelLeft, pixelTop) {  
	if (pixelLeft < pixelTableLeft - 10 ||
		pixelLeft > pixelTableRight + 10 ||
		pixelTop < pixelTableTop - 10 ||
		pixelTop > pixelTableBottom + 10)
		{
		return false;
		}
	
	return true;
}

function createMovingPiece(ColorAndPiece, i) {
	oElement = document.createElement('IMG');

	oElement.id = 'drag_' + ColorAndPiece + '_' + i;
	oElement.style.position = "absolute";
	oElement.src = root + ColorAndPiece + '.gif';

	document.body.appendChild(oElement);
}

function createMovingBucket(Color) {
	oElement = document.createElement('IMG');

	oElement.id = 'drag_c_' + Color + '_1';
	oElement.style.position = "absolute";
	oElement.src = root + 'c_' + Color + '.gif';

	document.body.appendChild(oElement);
}

function resetMovingPiece(ColorAndPieceAndNumber) {

	var elMoving = document.getElementById('drag_' + ColorAndPieceAndNumber);
	var elStatic = document.getElementById(ColorAndPieceAndNumber.substr(0,3));

	var pixelTop = DL_GetElementTop(elStatic);
	var pixelLeft = DL_GetElementLeft(elStatic);

	elMoving.style.top = pixelTop + "px";
	elMoving.style.left = pixelLeft + "px";
}

function resetBoard() {

	var i, x, y;

	for (i = 1; i < 9; i++) {
		resetMovingPiece('w_k_' + i);
		resetMovingPiece('w_q_' + i);
		resetMovingPiece('w_b_' + i);
		resetMovingPiece('w_n_' + i);
		resetMovingPiece('w_r_' + i);
		resetMovingPiece('w_p_' + i);
		resetMovingPiece('b_k_' + i);
		resetMovingPiece('b_q_' + i);
		resetMovingPiece('b_b_' + i);
		resetMovingPiece('b_n_' + i);
		resetMovingPiece('b_r_' + i);
		resetMovingPiece('b_p_' + i);
	}
	
	resetMovingPiece('c_x_1');
	resetMovingPiece('c_b_1');
	resetMovingPiece('c_r_1');
	resetMovingPiece('c_p_1');
	
	for (y = 1; y < 9; y++) {
		for (x = 1; x < 9; x++) {
			i = 8 * (y-1) + x;
			rgPiece[i] = "x_x";
			rgColor[i] = "x";
			setSquareColor(x, y, "x"); 
		}
	}
	
	cUndo = 0;
	iUndo = 0;
}

// Sets board dimensions globals 

function setTableCorners() {

	var el = getCellGivenIndex(1);

	pixelTableTop = DL_GetElementTop(el);
	pixelTableBottom = pixelTableTop + 7 * pixelCellSize;
	pixelTableLeft = DL_GetElementLeft(el);
	pixelTableRight = pixelTableLeft + 7 * pixelCellSize;
}

// Highlighs square "x,y"  with "color"

function setSquareColor(x, y, color) { 
	var elCell = getCellGivenIndex(getIndexGivenFileRank(x, y));
	elCell.style.background = getBGColor(x, y, color);
}

// get background color for square "x,y" highlighed with "color"

function getBGColor(x, y, color) {
	var new_bg =  rgBgColor[color + ((x+y) % 2)];
	return new_bg;
}

function setBackgroundColors() {
	rgBgColor['x' + 0]  = "#C2CBBC";
	rgBgColor['x' + 1]  = "#9B9A88";
	rgBgColor['b' + 0]  = "#BEC2F3";
	rgBgColor['b' + 1]  = "#8D73DD";
	rgBgColor['p' + 0]  = "#FFAEF1";
	rgBgColor['p' + 1]  = "#D865C4";
	rgBgColor['r' + 0]  = "#FCA596";
	rgBgColor['r' + 1]  = "#FE5F5F";
}

function createMovingPieces() {

	var i;

	for (i = 1; i < 9; i++) {
		createMovingPiece('w_k', i);
		createMovingPiece('w_q', i);
		createMovingPiece('w_b', i);
		createMovingPiece('w_n', i);
		createMovingPiece('w_r', i);
		createMovingPiece('w_p', i);
		createMovingPiece('b_k', i);
		createMovingPiece('b_q', i);
		createMovingPiece('b_b', i);
		createMovingPiece('b_n', i);
		createMovingPiece('b_r', i);
		createMovingPiece('b_p', i);
	}

	createMovingBucket('x');
	createMovingBucket('p');
	createMovingBucket('b');
	createMovingBucket('r');
}


function flipBoard() {
	
	var strBoard = createboarddataFENlike();
	var elTable = document.getElementById('board');
	var elRow, elCell;
	
	resetBoard();

	if (viewpoint == 'white')
		{
		for (iFile = 1; iFile < 9; iFile++)
			{
			elRow = elTable.rows[iFile+1];
			elCell = elRow.cells[0];
			elCell.innerHTML = '<FONT color=gray size=1>'+iFile+'</FONT>';
			}

		elRow = elTable.rows[10];
		
		for (iRank = 1; iRank < 9; iRank++)
			{
			elCell = elRow.cells[9 - iRank];
			elCell.innerHTML = '<FONT color=gray size=1>'+String.fromCharCode(64+iRank)+'</FONT>';
			}

		viewpoint = 'black';
		}
	else
		{
		for (file = 1; file < 9; file++)
			{
			elRow = elTable.rows[10-file];
			elCell = elRow.cells[0];
			elCell.innerHTML = '<FONT color=gray size=1>'+file+'</FONT>';
			}

		elRow = elTable.rows[10];
		
		for (iRank = 1; iRank < 9; iRank++)
			{
			elCell = elRow.cells[iRank];
			elCell.innerHTML = '<FONT color=gray size=1>'+String.fromCharCode(64+iRank)+'</FONT>';
			}
		
		viewpoint = 'white';
		}

	loadboardNewFormat(strBoard);
}

function KeyDown(e)
{
 if (!e) var e = window.event;

 var key = e.keyCode;
 var low_key = String.fromCharCode(key).toLowerCase();
 
 if(key==37 || key==100 || (e.ctrlKey && low_key == "z")) {	// Left Arrow and ctrl-z
   UndoOneMove();
 	}

 if(key==39 || key==102 || (e.ctrlKey && low_key == "y")) {	// Right Arrow and ctrl-y
	 RedoOneMove();
 	}

 if (e.ctrlKey && low_key == "p") { popupPrintWindow(); }

 if (e.ctrlKey && low_key == "d") { popupDiagramWindow(); }				   

 if (e.ctrlKey && low_key == "v") { loadboarddata(); }
 
 if (e.ctrlKey && low_key == "c") { 
	var boarddata = createboarddataFENlike();

	if (window.clipboardData)
		{
		// Firefox cannot do that, and hates when we try.
		
		window.clipboardData.setData("Text", boarddata);
		}
	}

 if (e.ctrlKey && low_key == "b") { return exportBB(); }
 if (e.ctrlKey && low_key == "h") { return exportHTML(); }
 	
 // Escape closes window if we are in a pop-up
 if (window.opener && key==27) { window.close(); }
 
}


function createboarddata() {
	
	var boarddata = createboarddataFENlike();

	document.getElementById('boardstring').value = boarddata;

	if (window.clipboardData)
		{
		// Firefox cannot do that, and hates when we try.
		
		window.clipboardData.setData("Text", boarddata);
		}
	
	return false; 
}


function createboarddataFENlike() {
	
	var board = createboarddataCore();
	return board.fen + ' ' + board.move + ' ' + board.size + ' ' + board.colors;
}


function popupHelpWindow(root) { 
	if (!root) root = '';
	window.open(root + "MCDWizardHelp.html", "MCDWizardHelp", 
   		"width=700,height=500,scrollbars=yes,resizable=yes");   
};


function popupDiagramWindow() 
{
var WinSettings = "width=333, height=333, location=no, menubar=yes, status=no, resizable=yes, scrollbars=no";
var myWindow = window.open("diagramlink", "diagramWindow", WinSettings);
var board = createboarddataCore();

var urlImage = 'http://www.mrfixitonline.com/cd/e/f%3D' + 
					((board.fen == '') ? '8/8/8/8/8/8/8/8' : board.fen) + 
					'~s%3D' + board.size +
					'~m%3D' + board.move + 
					((board.colors == '') ? '' : '~c%3D' + board.colors) +
					'.fen.png';

var boarddata = escape(createboarddataFENlike());
var urlWizard = 'http://www.mrfixitonline.com/cd/mcdwa.html?f='+ boarddata;

var htmlLink = '<a href="' + urlWizard + '"><img src="' + urlImage + '" border="0" alt="" /></a>';

var htmlWindow = '<html><head><title>To copy: Ctlr-A, Ctrl-C, Esc</title>' + 
					' <script language="Javascript">' +
					'	document.onkeydown = KeyDown;' + 
					' 	function KeyDown()	' +
					'	{	' +
					' 	 var key = event.keyCode;	' +
					'	 var strKey = String.fromCharCode(key).toLowerCase();	' +
					'	 if(key==27)	' +
					' 	   window.close();	' +
					'	}	' +
					' 	</script>	' +
			'</head>' +
			'<body style="text-align: center;">' + htmlLink + '</body></html>';

myWindow.document.write(htmlWindow);
myWindow.document.close();
}


function popupPrintWindow() 
{
var WinSettings = "width=330, height=300, location=no, menubar=yes, status=no, resizable=yes, scrollbars=no";
var myWindow = window.open("Esc2Close", "printWindow", WinSettings);
var board = createboarddataCore();
board.size = "L";

var htmlWindow = '<html><head><title>DiagramWizard Printer-friendly page</title></head>' +
			'<body onload="self.print()"><center>' +
			'<IMG alt="" src="' + imageSrcFromBoard(board) +
			'" border=2></center></body></html>';

myWindow.document.write(htmlWindow);
myWindow.document.onkeydown = function () {	myWindow.close(); } ;
myWindow.document.close();
}


function exportHTML() 
{ 
var board = createboarddataCore();
var urlImage = 'http://www.mrfixitonline.com/cd/e/f%3D' + 
					((board.fen == '') ? '8/8/8/8/8/8/8/8' : board.fen) + 
					'~s%3D' + board.size +
					'~m%3D' + board.move + 
					((board.colors == '') ? '' : '~c%3D' + board.colors) +
					'.fen.png';

var html = '<a href="' + urlWizard() + '"><img src="' + urlImage + '" border="0" alt="" /></a>';

document.getElementById('boardstring').value = html;
	
if (window.clipboardData)	{
	// Firefox cannot do that, and hates when we try.
	 window.clipboardData.setData("Text", html);
	}

return false; 
}


function exportBB() 
{ 
var board = createboarddataCore();
var urlImage = 'http://www.mrfixitonline.com/cd/e/f%3D' + 
					((board.fen == '') ? '8/8/8/8/8/8/8/8' : board.fen) + 
					'~s%3D' + board.size +
					'~m%3D' + board.move + 
					((board.colors == '') ? '' : '~c%3D' + board.colors) +
					'.fen.png';

var bbcode = '[url=' + urlWizard() + '][img]' + urlImage + '[/img][/url]';

document.getElementById('boardstring').value = bbcode;
	
if (window.clipboardData)	{
	// Firefox cannot do that, and hates when we try.
	 window.clipboardData.setData("Text", bbcode);
	}

return false; 
}


function urlWizard() 
{ 
var boarddata = escape(createboarddataFENlike());
var url = 'http://www.mrfixitonline.com/cd/mcdwa.html?f='+ boarddata;
	
if (nHalfMovesInit > 1)
	{
	var nHalfMoves = nHalfMovesInit;
	var i;

	// code copied from DisplayHistory - avoid duplication???  

	for (i = 1; i <= iUndo; i++)
		{		
		var fCount;
		
		if (rgUndoMoveType[i].charAt(0) == '1')
			{
			// first part of castling or capture - skip it

			fCount = false;
			}
		else if (rgUndoMoveType[i] == '0C')
			{
			// Coloring pseudo-move - skip it
		
			fCount = false;
			}
		else if (rgUndoMoveType[i] == '0S')
			{
			// setup - skip it
		
			fCount = false;
			}
		else if (rgUndoMoveType[i] == '2C')
			{
			// castling
		
			fCount = true;
			}
		else 
			{
			// we do have normal move or second part of capture

			fCount = true;
			}

		if (fCount)
			{
			nHalfMoves ++;
			}
    }
	
	url += "&n=" + nHalfMoves;
	}

return url; 
}


function noenter(e) 
{ 
if (!e) var e = window.event;
if (e.keyCode == 13)
	{
	DisplayHistory();

	return false;
	}
return true; 
}


function initDiagramBuilder(urlRoot) {
	root = urlRoot;
	rgPiece = new Array();
	rgColor = new Array();
	rgBgColor = new Array();
	createMovingPieces();
	setBackgroundColors();
	setTableCorners();
	resetBoard();
	loadblankboard();
	
	document.onmousedown = grabEl;
	document.onkeydown = KeyDown;
}

/* Client-side access to querystring name=value pairs
	Version 1.2.3
	22 Jun 2005
	Adam Vandenberg
*/

function Query(qs) { /* optionally pass a querystring to parse */

	this.params = new Object();
	
	this.get = function(key, default_) 
					{					
					if (default_ == null) default_ = null;		/* This silly looking line changes UNDEFINED to NULL */
					
					var value=this.params[key];
					
					if (value==null) value=default_;
					
					return value;
					};
	
	if (qs == null)
		qs=location.search.substring(1,location.search.length);

	if (qs.length == 0) return;

	/* Turn <plus> back to <space>
		 See: http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4.1 */
	
	qs = qs.replace(/\+/g, ' ');
	
	var args = qs.split('&');									/* parse out name/value pairs separated via & */
		
	// split out each name=value pair
	
	for (var i=0;i<args.length;i++) {
		var value;
		var pair = args[i].split('=');
		var name = unescape(pair[0]);

		if (pair.length == 2)
			value = unescape(pair[1]);
		else
			value = name;
		
		this.params[name] = value;
	}
}


function imageSrcFromBoard(board) 
{
return root + 'cd.php?f=' +
			((board.fen == '') ? '8/8/8/8/8/8/8/8' : board.fen) + '&s=' + board.size +
			'&m=' + board.move + ((board.colors == '') ? '' : '&c=' + board.colors);
}

// Places pieces one by one, strFreeFiles contains remaining free places.

function generate960FenLine(cSeed) {

	var seed1, seed2;
	var index, iFile, cFile, cPiece;
	var strFreeFiles = '12345678';		// list of free squares
	var strFEN = '12345678';			// will contain the result in the end
	var strKRN;
	var KRNcode = new Array('NNRKR','NRNKR','NRKNR','NRKRN','RNNKR','RNKNR','RNKRN','RKNNR','RKNRN','RKRNN');

	// random seed must be between 0 and 960. BTW, 518 generates standard initial position.

	seed2 = parseInt(cSeed) % 960;

	// placing light-squared (for white) bishop
	// seed 1 gives one of the 4 possible positions.

	seed1 = seed2 % 4;
	seed2 = Math.floor(seed2 / 4);
	iFile = 2 + seed1 * 2;
	
	cFile = iFile.toString();
	strFreeFiles = DeleteNumber(strFreeFiles, cFile);
	strFEN = ReplaceNumber(strFEN, cFile, 'B');

	// placing black-squared (for white) bishop

	seed1 = seed2 % 4;
	seed2 = Math.floor(seed2 / 4);
	iFile = 1 + seed1 * 2;
	
	cFile = iFile.toString();
	strFreeFiles = DeleteNumber(strFreeFiles, cFile);
	strFEN = ReplaceNumber(strFEN, cFile, 'B');

	// placing queen on one of five remaining places

	seed1 = seed2 % 6;
	seed2 = Math.floor(seed2 / 6);

	cFile = strFreeFiles.substr(seed1, 1)

	strFreeFiles = DeleteNumber(strFreeFiles, cFile);
	strFEN = ReplaceNumber(strFEN, cFile, 'Q');	
	
	// Placing the rest of the pieces
	// Knights, rooks are interchangeable. King must be placed between the two rooks.
	// That leaves 10 variants, enumerated in KRNcode array

	// Notice where rooks and king go to initialize castle string
	
	strKRN = KRNcode[seed2];

	for (index = 0; index < 5; index++) 
		{
		cFile = strFreeFiles.substr(index, 1);
		cPiece = strKRN.substr(index, 1);
		strFEN = ReplaceNumber(strFEN, cFile, cPiece);		
		}

	return strFEN;
}

function DeleteNumber(strFiles, strNumber) {
	re = new RegExp(strNumber)
	return strFiles.replace(re, '');
}

function ReplaceNumber(strFiles, strNumber, strPiece) {
	re = new RegExp(strNumber)
	return strFiles.replace(re, strPiece);
}

