API Docs for:
Show:

File: js/auxiliary.js

/**
Auxuliary methods
@module Auxuliary
**/

/**
Auxuliary methods
This is not actually a class, but a necessary convention to get YUIdoc to document standalone items.
@class Auxuliary
*/

/**
 * draws rounded rectangle on the canvas plane
 * credit: http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas/7592676#7592676
 * @method roundRect
 * @param {Number} ctx canvas context
 * @param {Number} x x coordinate on the canvas plane
 * @param {Number} y y coordinate on the canvas plane
 * @param {Number} width width of the rectangle
 * @param {Number} height height of the rectangle
 * @param {Number} radius corner radius
 * @param {Boolean} fill fill boolean flag
 * @param {Boolean} stroke stroke boolean flag 
 */
function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
    if (typeof stroke == 'undefined') {
        stroke = true;
    }
    if (typeof radius === 'undefined') {
        radius = 5;
    }
    if (typeof radius === 'number') {
        radius = {tl: radius, tr: radius, br: radius, bl: radius};
    } else {
        var defaultRadius = {tl: 0, tr: 0, br: 0, bl: 0};
        for (var side in defaultRadius) {
            radius[side] = radius[side] || defaultRadius[side];
        }
    }
    
    ctx.beginPath();
    ctx.moveTo(x + radius.tl, y);
    ctx.lineTo(x + width - radius.tr, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
    ctx.lineTo(x + width, y + height - radius.br);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
    ctx.lineTo(x + radius.bl, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
    ctx.lineTo(x, y + radius.tl);
    ctx.quadraticCurveTo(x, y, x + radius.tl, y);
    ctx.closePath();
    if (fill) {
        ctx.fill();
    }
    if (stroke) {
        ctx.stroke();
    }
}

 /**
 * converts coordinates of the chess board to a coordinates of the canvas plane
 * @method getCanvasCoordinates
 * @param {Number} x x coordinate on the canvas plane
 * @param {Number} y y coordinate on the canvas plane
 * @param {Number} fieldsize size of the chess field
 * @return {Object} coordinates on the canvas plane
 */
function getCanvasCoordinates(x,y,fieldsize) {
    
    if(board.side == "black") {
        return {
            x: (7 - x) * fieldsize,
            y: (7 - y) * fieldsize
        }
    }
    
    return {
        x: x * fieldsize,
        y: y * fieldsize
    }
}

 /**
 * removes an elements from an array with a given value
 * credit: http://stackoverflow.com/questions/281264/remove-empty-elements-from-an-array-in-javascript/281335#281335
 * @method clean
 * @param {Object} deleteValue a values to delete
 * @return {Array} cleaned array
 */
Array.prototype.clean = function(deleteValue) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == deleteValue) {         
      this.splice(i, 1);
      i--;
    }
  }
  return this;
};

 /**
 * converts mouse coordinates to a coordinates on the chess board
 * @method getMousePos
 * @param {Object} c canvas context
 * @param {Object} evt mouse event 
 * @return {Object} coordinates on chess board
 */
function getMousePos(c, evt) {
    var rect = c.getBoundingClientRect();
    var fieldSize = c.width / 8;
    
    return {
        x: Math.floor((evt.clientX - rect.left)/fieldSize),
        y: Math.floor((evt.clientY - rect.top)/fieldSize)
    };
}

 /**
 * converts mouse coordinates to a coordinates on the chess board invarian of the side perspective
 * @method getChessCoordinates
 * @param {Object} evt mouse event 
 * @return {Object} player invariant coordinates on chess board
 */
function getChessCoordinates(evt) {
    
    var c = $('#chess-board').get(0);
    var rect = c.getBoundingClientRect();
    var fieldSize = c.width / 8;
    
    if(board.side == "black") {
        return {
            x: 7 - Math.floor((evt.clientX - rect.left)/fieldSize),
            y: 7 - Math.floor((evt.clientY - rect.top)/fieldSize)
        };
    }
    
    return {
        x: Math.floor((evt.clientX - rect.left)/fieldSize),
        y: Math.floor((evt.clientY - rect.top)/fieldSize)
    };
}

/**
 * checks if string represents a valud positive integer
 * credit: http://stackoverflow.com/questions/10834796/validate-that-a-string-is-a-positive-integer/10834843#10834843
 * @method isNormalInteger
 * @param {String} str string to be checked
 * @return {Boolean} true if an input is a positive integer, false otherwise
 */
function isNormalInteger(str) {
    return /^\+?(0|[1-9]\d*)$/.test(str);
}

/**
 * converts piece notation symbol to a HTML Entitiy, representing a piece
 * @method getHTMLcharFromNotation
 * @param {String} str piece notation symbol
 * @param {String} color color of the piece, valid values are 'black' and 'white'
 * @return {String} HTML Entity
 */
function getHTMLcharFromNotation(val, color) {
	if(val == "0-0") return val;
	if(val == "0-0-0") return val;
	
	var res = val;
	
	if(color == "white") {
		if(val.indexOf("K") > -1) res = res.replace("K", "&#9812;");
		if(val.indexOf("Q") > -1) res = res.replace("Q", "&#9813;");
		if(val.indexOf("R") > -1) res = res.replace("R", "&#9814;");
		if(val.indexOf("B") > -1) res = res.replace("B", "&#9815;");
		if(val.indexOf("N") > -1) res = res.replace("N", "&#9816;");
		if(val.indexOf("p") > -1) res = res.replace("p", "&#9817;");
	} else {
		if(val.indexOf("K") > -1) res = res.replace("K", "&#9818;");
		if(val.indexOf("Q") > -1) res = res.replace("Q", "&#9819;");
		if(val.indexOf("R") > -1) res = res.replace("R", "&#9820;");
		if(val.indexOf("B") > -1) res = res.replace("B", "&#9821;");
		if(val.indexOf("N") > -1) res = res.replace("N", "&#9822;");
		if(val.indexOf("p") > -1) res = res.replace("p", "&#9823;");
	}
	
	return res;
}

/**
 * converts unix timestamp to a human readable string in mm:ss format
 * @method unixTimeStampToTimerString
 * @param {Number} ts unix timestamp
 * @return {String} time in mm:ss format
 */
function unixTimeStampToTimerString(ts) {
	var date = new Date(ts*1000);
	var minutes = "0" + date.getMinutes();
	var seconds = "0" + date.getSeconds();
	var formattedTime = minutes.substr(-2) + ':' + seconds.substr(-2);
	return formattedTime;
}

/**
 * Increments chess coordinates to a given diagonal direction. Helper method.  
 * @method getBishopDirections
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} direction direction to increment. Valid values are 'up-right', 'up-left', 'down-right' and 'down-left'
 * @return {Object} incremented chess coordinates
 */
function getBishopDirections(x, y, direction, i) {
	
	if(direction == "up-right") {
		return {x:x+i,y:y-i};
	};

	if(direction == "up-left") {
		return {x:x-i,y:y-i};
	};

	if(direction == "down-right") {
		return {x:x+i,y:y+i};
	};

	if(direction == "down-left") {
		return {x:x-i,y:y+i};
	};
}

/**
 * Increments chess coordinates to a given lateral direction. Helper method.  
 * @method getRookDirections
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} direction direction to increment. Valid values are 'right', 'left', 'down' and 'up'
 * @return {Object} incremented chess coordinates
 */
function getRookDirections(x, y, direction, i) {
	
	if(direction == "right") {
		return {x:x+i,y:y};
	};

	if(direction == "left") {
		return {x:x-i,y:y};
	};

	if(direction == "up") {
		return {x:x,y:y+i};
	};

	if(direction == "down") {
		return {x:x,y:y-i};
	};
}

/**
 * calculates moves in a diagonal directions given an initial coordinates and a direction. Helper method.
 * @method getBishopLegalMovesHelper
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the piece, valid values are 'black' and 'white'
 * @param {String} direction direction to increment. Valid values are 'up-right', 'up-left', 'down-right' and 'down-left'
 * @return {Array} an array of moves
 */
function getBishopLegalMovesHelper(x,y,color, direction) {
	
	var moves = [];
    
    parentLoop:
    for(var i = 1; i < 9; i++) {
		
        var curCoor = getBishopDirections(x, y, direction, i);

		curX = curCoor.x;
		curY = curCoor.y;
		
        if(curX > 7 || curY > 7 || curX < 0 || curY < 0) break;

        for(var j = 0; j < board.pieces.length; j++) {
            if(board.pieces[j].X == curX && board.pieces[j].Y == curY && board.pieces[j].color == color) { 
                break parentLoop; 
            } 

            if(board.pieces[j].X == curX && board.pieces[j].Y == curY && board.pieces[j].color != color) { 
                moves.push({x:curX, y:curY});
                break parentLoop; 
            } 
        }

        moves.push({x:curX, y:curY});
    }
	
	return moves;
}

 /**
 * calculates moves in a lateral directions given an initial coordinates and a direction. Helper method.
 * @method getRookLegalMovesHelper
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the piece, valid values are 'black' and 'white'
 * @param {String} direction direction to increment. Valid values are 'right', 'left', 'down' and 'up'
 * @return {Array} an array of moves
 */
function getRookLegalMovesHelper(x,y,color, direction) {
	
	var moves = [];
    
    parentLoop:
    for(var i = 1; i < 9; i++) {
		
		var curCoor = getRookDirections(x, y, direction, i);

		curX = curCoor.x;
		curY = curCoor.y;

        if(curX > 7 || curY > 7 || curX < 0 || curY < 0) break;

        for(var j = 0; j < board.pieces.length; j++) {
            if(board.pieces[j].X == curX && board.pieces[j].Y == curY && board.pieces[j].color == color) { 
                break parentLoop; 
            } 

            if(board.pieces[j].X == curX && board.pieces[j].Y == curY && board.pieces[j].color != color) { 
                moves.push({x:curX, y:curY});
                break parentLoop; 
            } 
        }

        moves.push({x:curX, y:curY});
    }
	
	return moves;
}

/**
 * calculates coordinate of the field behind the opponent King in a diagonal directions given an initial 
 * coordinates of the atacking piece and direction. 
 * Necessary for calculation of the King's legal moves. Helper method.
 * @method getBishopFieldBehindHelper
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the atacking piece, valid values are 'black' and 'white'
 * @param {String} direction direction to increment. Valid values are 'up-right', 'up-left', 'down-right' and 'down-left'
 * @return {Object} a coordinate of the field behind the opponent's king
 */
function getBishopFieldBehindHelper(x,y,color,direction) {
	var flag = false;
    parentLoop:
    for(var i = 1; i < 9; i++) {
		
		var curCoor = getBishopDirections(x, y, direction, i);

		curX = curCoor.x;
		curY = curCoor.y;

        if(curX > 7 || curY > 7 || curX < 0 || curY < 0) break;
        
        if(flag) return {x:curX, y:curY};

        for(var j = 0; j < board.pieces.length; j++) {
			
			if(board.pieces[j].X == curX 
               && board.pieces[j].Y == curY 
               && board.pieces[j].type != "King") {
				return null;
			}
			
            if(board.pieces[j].X == curX 
               && board.pieces[j].Y == curY 
               && board.pieces[j].type == "King") {
				
				if(board.pieces[j].color == color) {
					return null;
				}
				
				flag = true;
				break;
			}
        }
    }
}

/**
 * calculates coordinate of the field behind the opponent King in a lateral directions given an initial 
 * coordinates of the atacking piece and direction. 
 * Necessary for calculation of the King's legal moves. Helper method.
 * @method getRookFieldBehindHelper
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the atacking piece, valid values are 'black' and 'white'
 * @param {String} direction direction to increment. Valid values are 'right', 'left', 'down' and 'up'
 * @return {Object} a coordinate of the field behind the opponent's king
 */
function getRookFieldBehindHelper(x,y,color,direction) {
	var flag = false;
    
    parentLoop:
    for(var i = 1; i < 9; i++) {
		
		var curCoor = getRookDirections(x, y, direction, i);

		curX = curCoor.x;
		curY = curCoor.y;

        if(curX > 7 || curY > 7 || curX < 0 || curY < 0) break;

        if(flag) return {x:curX, y:curY};

        for(var j = 0; j < board.pieces.length; j++) {
			
			if(board.pieces[j].X == curX 
               && board.pieces[j].Y == curY 
               && board.pieces[j].type != "King") {
				return null;
			}
			
            if(board.pieces[j].X == curX 
               && board.pieces[j].Y == curY 
               && board.pieces[j].type == "King") {
				
				if(board.pieces[j].color == color) {
					return null;
				}
				
				flag = true;
				break;
			}
        }
    }
}

/**
 * calculates an array of fields covered by a piece in diagonal directions given an initial 
 * coordinates of the piece and direction. Helper method.
 * @method getBishopCoveredFieldsHelper
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the atacking piece, valid values are 'black' and 'white'
 * @param {String} direction direction to increment. Valid values are 'right', 'left', 'down' and 'up'
 * @return {Array} an array of fields covered by a piece
 */
function getBishopCoveredFieldsHelper(x,y,color, direction) {
	
	var moves = [];
    
    parentLoop:
    for(var i = 1; i < 9; i++) {
		
        var curCoor = getBishopDirections(x, y, direction, i);

		curX = curCoor.x;
		curY = curCoor.y;

        if(curX > 7 || curY > 7 || curX < 0 || curY < 0) break;

        for(var j = 0; j < board.pieces.length; j++) {
            if(board.pieces[j].X == curX && board.pieces[j].Y == curY) { 
                moves.push({x:curX, y:curY});
                break parentLoop; 
            } 
        }

        moves.push({x:curX, y:curY});
    }
	
	return moves;
}

/**
 * calculates an array of fields covered by a piece in lateral directions given an initial 
 * coordinates of the piece and direction. Helper method.
 * @method getRookCoveredFieldsHelper
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the atacking piece, valid values are 'black' and 'white'
 * @param {String} direction direction to increment. Valid values are 'right', 'left', 'down' and 'up'
 * @return {Array} an array of fields covered by a piece
 */
function getRookCoveredFieldsHelper(x,y,color, direction) {
	
	var moves = [];
    
    parentLoop:
    for(var i = 1; i < 9; i++) {
		
        var curCoor = getRookDirections(x, y, direction, i);

		curX = curCoor.x;
		curY = curCoor.y;

        if(curX > 7 || curY > 7 || curX < 0 || curY < 0) break;

        for(var j = 0; j < board.pieces.length; j++) {
            if(board.pieces[j].X == curX && board.pieces[j].Y == curY) { 
                moves.push({x:curX, y:curY});
                break parentLoop; 
            }
        }

        moves.push({x:curX, y:curY});
    }
	
	return moves;
	
}

/**
 * calculates an array of legal moves for a piece in a diagonal directions
 * @method getBishopLegalMoves
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the piece, valid values are 'black' and 'white'
 * @return {Array} an array of legal moves
 */
function getBishopLegalMoves(x,y,color) {
    
	var moves = [];
    
	var moves1 = getBishopLegalMovesHelper(x,y,color, "up-right");
	var moves2 = getBishopLegalMovesHelper(x,y,color, "up-left");
	var moves3 = getBishopLegalMovesHelper(x,y,color, "down-right");
	var moves4 = getBishopLegalMovesHelper(x,y,color, "down-left");
	
	return moves = moves.concat(moves1, moves2, moves3, moves4);
}

/**
 * calculates an array of covered fields for a piece in a diagonal directions
 * @method getBishopCoveredFields
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the piece, valid values are 'black' and 'white'
 * @return {Array} an array of covered fields
 */
function getBishopCoveredFields(x,y,color) {
    
    var moves = [];
    
	var moves1 = getBishopCoveredFieldsHelper(x,y,color, "up-right");
	var moves2 = getBishopCoveredFieldsHelper(x,y,color, "up-left");
	var moves3 = getBishopCoveredFieldsHelper(x,y,color, "down-right");
	var moves4 = getBishopCoveredFieldsHelper(x,y,color, "down-left");
	
	return moves = moves.concat(moves1, moves2, moves3, moves4);
	
}

/**
 * calculates an array of legal moves for a piece in a lateral directions
 * @method getRookLegalMoves
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the piece, valid values are 'black' and 'white'
 * @return {Array} an array of legal moves
 */
function getRookLegalMoves(x,y,color) {
    
    var moves = [];
    
	var moves1 = getRookLegalMovesHelper(x,y,color, "up");
	var moves2 = getRookLegalMovesHelper(x,y,color, "down");
	var moves3 = getRookLegalMovesHelper(x,y,color, "left");
	var moves4 = getRookLegalMovesHelper(x,y,color, "right");
	
	return moves = moves.concat(moves1, moves2, moves3, moves4);
}

/**
 * calculates an array of covered fields for a piece in a lateral directions
 * @method getRookCoveredFields
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the piece, valid values are 'black' and 'white'
 * @return {Array} an array of covered fields
 */
function getRookCoveredFields(x,y,color) {
    
    var moves = [];
    
	var moves1 = getRookCoveredFieldsHelper(x,y,color, "up");
	var moves2 = getRookCoveredFieldsHelper(x,y,color, "down");
	var moves3 = getRookCoveredFieldsHelper(x,y,color, "left");
	var moves4 = getRookCoveredFieldsHelper(x,y,color, "right");
	
	return moves = moves.concat(moves1, moves2, moves3, moves4);
}

/**
 * calculates coordinate of the field behind the opponent King in a diagonal directions given an initial 
 * coordinates of the atacking piece 
 * @method getBishopFieldBehind
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the atacking piece, valid values are 'black' and 'white'
 * @return {Object} a coordinate of the field behind the opponent's king
 */
function getBishopFieldBehind(x,y,color) {
    
    var fieldBehind;
	
	fieldBehind = getBishopFieldBehindHelper(x,y,color,"up-right");
    if(fieldBehind != null) return fieldBehind;
	
	fieldBehind = getBishopFieldBehindHelper(x,y,color,"up-left");
    if(fieldBehind != null) return fieldBehind;
	
	fieldBehind = getBishopFieldBehindHelper(x,y,color,"down-right");
    if(fieldBehind != null) return fieldBehind;
	
	fieldBehind = getBishopFieldBehindHelper(x,y,color,"down-left");
    if(fieldBehind != null) return fieldBehind;
	
   	return null;
}

/**
 * calculates coordinate of the field behind the opponent King in a lateral directions given an initial 
 * coordinates of the atacking piece 
 * @method getRookFieldBehind
 * @param {Number} x X coordinate of the field on the chess board
 * @param {Number} y Y coordinate of the field on the chess board
 * @param {String} color color of the atacking piece, valid values are 'black' and 'white'
 * @return {Object} a coordinate of the field behind the opponent's king
 */
function getRookFieldBehind(x,y,color) {
    
	var fieldBehind;
	
	fieldBehind = getRookFieldBehindHelper(x,y,color,"right");
    if(fieldBehind != null) return fieldBehind;
	
	fieldBehind = getRookFieldBehindHelper(x,y,color,"left");
    if(fieldBehind != null) return fieldBehind;
	
	fieldBehind = getRookFieldBehindHelper(x,y,color,"up");
    if(fieldBehind != null) return fieldBehind;
	
	fieldBehind = getRookFieldBehindHelper(x,y,color,"down");
    if(fieldBehind != null) return fieldBehind;
	
   	return null;
}

/**
 * removes captured piece from a pieces array of the board object
 * @method removeCapturedPiece
 * @param {Number} x X coordinate of the captured piece on the chess board
 * @param {Number} y Y coordinate of the captured piece on the chess board
 * @return {Boolean} true if piece is found, false otherwise
 */
function removeCapturedPiece(x,y) {

	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].X == x && board.pieces[i].Y == y) {

			if(board.pieces[i].X == 0 && board.pieces[i].Y == 0) board.blackCanCastleLong 	= "false";
			if(board.pieces[i].X == 7 && board.pieces[i].Y == 0) board.blackCanCastleShort 	= "false";
			if(board.pieces[i].X == 7 && board.pieces[i].Y == 7) board.whiteCanCastleShort 	= "false";
			if(board.pieces[i].X == 0 && board.pieces[i].Y == 7) board.whiteCanCastleLong 	= "false";
			
			board.pieces[i] = null;
			return true;
		}
	}
	
	return false;
}

/**
 * check whatever is King under atack
 * @method isKingAttacked
 * @param {String} color color of the King
 * @return {Boolean} true if King is under atack, false otherwise
 */
function isKingAttacked(color) {
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].color == color && board.pieces[i].type == "King") 
			var king = board.pieces[i];
	}
	
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].color != color) {
			var cf = board.pieces[i].getCoveredFields();
			for(var j = 0; j < cf.length; j++) {
				if(cf[j].x == king.X && cf[j].y == king.Y) return true;
			}
		}
	}
	
	return false;
}

/**
 * filters an array of legal moves for a given piece, restricting the movement of a piece in a such a way 
 * that King can not be atacked by opponent piece
 * @method preventCheck
 * @param {Object} piece piece, movement of which to be restricted
 * @param {Array} legalMoves an array of legal moves of the piece
 * @return {Array} filtered array of a legal moves
 */
function preventCheck(piece, legalMoves) {
	var originalPosition = {x:piece.X, y:piece.Y};
	var legalMove = null;
	
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].ID == piece.ID) {

			//defend from check by capture the atacking piece
			parentLoop:
			for(var j = 0; j < legalMoves.length; j++) {
				for(var k = 0; k < board.pieces.length; k++) {
					if(board.pieces[k].X == legalMoves[j].x && board.pieces[k].Y == legalMoves[j].y) {
						var pieceToKill = board.pieces[k];

						board.pieces[i].X = legalMoves[j].x;
						board.pieces[i].Y = legalMoves[j].y;
						board.pieces.splice(k,1);

						if(!isKingAttacked(piece.color)) {
							board.pieces.splice(k, 0, pieceToKill);
							board.pieces[i].X = originalPosition.x;
							board.pieces[i].Y = originalPosition.y;
							legalMove = legalMoves[j];
							break parentLoop;
						} 

						board.pieces.splice(k, 0, pieceToKill);
						board.pieces[i].X = originalPosition.x;
						board.pieces[i].Y = originalPosition.y;
					} 
				}
			}

			//defend from check by blocking the atacking piece
			for(var j = 0; j < legalMoves.length; j++) {
				board.pieces[i].X = legalMoves[j].x;
				board.pieces[i].Y = legalMoves[j].y;

				if(isKingAttacked(piece.color)) {
					board.pieces[i].X = originalPosition.x;
					board.pieces[i].Y = originalPosition.y;
					legalMoves[j] = null;
				} else {
					board.pieces[i].X = originalPosition.x;
					board.pieces[i].Y = originalPosition.y;
				}
			}
		}
	}

	legalMoves.push(legalMove);

	return legalMoves.clean(null);
}

/**
 * generates move summary of a given input data
 * that King can not be atacked by opponent piece
 * @method getMoveSummary
 * @param {Object} piece a piece, which move is summarised
 * @param {Object} alternativePieces an array of pieces if the same type, which can reach the same destination field
 * @param {Object} origin coordinates of origin
 * @param {Object} destination coordinates of destination
 * @param {String} castling a string represents a castling, valid values are 'short' for king side castling,
 * 'long' for queen side castling or empty string if the move was not a castling
 * @param {Boolean} isCapture a boolean flag indicating if the move was a capture
 * @param {Boolean} isCheck a boolean flag indicating if the move was a check against an opponent king
 * @param {Boolean} isMate a boolean flag indicating if the move was a checkmate against the opponent
 * @param {Boolean} isStalemate a boolean flag indicating if the move achieved a stalemate
 * @param {String} promotion a string indicating that the move was a promotion of a pawn. 
 * Valid values are 'Q' for Queen, 'R' for the Rook, 'N' for the Knight, 'B' for the Bishop or 'none' if the move was not a promotion
 * @param {String} enpassant notation coordinates of the pawn indicating that the pawn can be taken en passant
 * @return {Object} an object represents a summary of the move
 */
function getMoveSummary(piece, 
						 alternativePieces,
						 origin,
						 destination,
						 castling,
						 isCapture,
						 isCheck,
						 isMate,
						 isStalemate,
						 promotion,
						 enpassant) {
	var move = '';
	
	if(castling == "short") {
		move = "0-0";
	} else if(castling == "long") {
		move = "0-0-0";
	} else {
		if(alternativePieces.length == 0) {
			if(isCapture) {
				move = piece  + "x" + getNotationCoordinates(destination);
			} else {
				move = piece + getNotationCoordinates(destination);
			}
			
			if(promotion != "none") {
				move = move + "=" + promotion;
			}
		} else {
			var shareX = false;
			var shareY = false;
			
			for(var i = 0; i < alternativePieces.length; i++) {
				for(var j = 0; j < alternativePieces.length; j++) {
					if(alternativePieces[i].X == alternativePieces[j].X && alternativePieces[i].ID != alternativePieces[j].ID) { 
						shareX = true;
					}
				}
			}
			
			for(var i = 0; i < alternativePieces.length; i++) {
				for(var j = 0; j < alternativePieces.length; j++) {
					if(alternativePieces[i].Y == alternativePieces[j].Y && alternativePieces[i].ID != alternativePieces[j].ID) {
						shareY = true;
					}
				}
			}
			
			if(!shareX && !shareY) piece = piece + getXNotationCoordinate(origin.x);
			if(shareX && !shareY) piece = piece + getYNotationCoordinate(origin.y);
			if(!shareX && shareY) piece = piece + getXNotationCoordinate(origin.x);
			if(shareX && shareY) piece = piece + getNotationCoordinates(origin);
			
			if(isCapture) {
				move = piece  + "x" + getNotationCoordinates(destination);
			} else {
				move = piece + getNotationCoordinates(destination);
			}
		}
	}
		
	if(isCheck && !isMate) move = move + "+";
	if(isMate) move = move + "#";
	
	return summary = {
		move:			move,
		castling:		castling,
		isCapture:		isCapture,
		isCheck:		isCheck,
		isMate:			isMate,
		isStalemate:	isStalemate,
		promotion:		promotion,
		enpassant:		enpassant
	}
}

/**
 * checks whatever the move is a legal move for a given piece
 * @method confirmMove
 * @param {Object} piece a piece to check the validity of the move
 * @param {Number} x X coordinate of the destination field on the chess board
 * @param {Number} y Y coordinate of the destination field on the chess board
 * @return {Boolean} true if the move is a legal move for a given piece, false otherwise
 */
function confirmMove(x,y,piece) {
	var legalMoves = piece.getLegalMoves();
        
	var found = false;
	for(var i = 0; i < legalMoves.length; i++) {
		if(legalMoves[i].x == x && legalMoves[i].y == y) { 
			found = true;
			break;
		}
	}
	return found;
}

/**
 * generates move summary of the move for a given piece
 * @method finishMove
 * @param {Object} piece a piece to move
 * @param {Number} x X coordinate of the destination field on the chess board
 * @param {Number} y Y coordinate of the destination field on the chess board
 * @return {Object} an object represents a summary of the move
 */
function finishMove(x,y,piece) {
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].color != piece.color && board.pieces[i].type == "Pawn") 
			board.pieces[i].canBeTakenEnPassant = false;
	}
	
	var _isCapture = removeCapturedPiece(x,y);
	board.pieces = board.pieces.clean(null);
	
	var alternativePieces = [];
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].type == piece.type && board.pieces[i].color == piece.color && board.pieces[i].ID != piece.ID) {
			var legalMoves = board.pieces[i].getLegalMoves();
			for(var j = 0; j < legalMoves.length; j++) {
				if(legalMoves[j].x == x && legalMoves[j].y == y) {
					alternativePieces.push(board.pieces[i]);
				}
			}
		}
	}
	
	if(alternativePieces.length > 0) alternativePieces.push(jQuery.extend(true, {}, piece));

	var origin = {x:piece.X,y:piece.Y};
	var destination = {x:x,y:y};
	
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].ID == piece.ID) {
			board.pieces[i].X = x;
			board.pieces[i].Y = y;
		}
	}
	
	board.drawMove(origin, destination, piece);
	board.changeSideToMove();
	
	var targetColor;
	if(piece.color == "white") 
		targetColor = "black";
	else
		targetColor = "white";

	var _isCheck		= isKingAttacked(targetColor);
	var _isMate 		= isMate(targetColor);
	var _isStalemate 	= isStalemate(targetColor);
	
	if(_isCapture) {
		board.drawMoves = 0;
	} else {
		board.drawMoves++;
	}

	return getMoveSummary(
		piece.notationName, 
		alternativePieces, 
		origin, 
		destination, 
		"none", 
		_isCapture, 
		_isCheck, 
		_isMate, 
		_isStalemate, 
		"none", 
		"none");
}

/**
 * converts chess coordinate to a notation coordinates string for a given field
 * @method getNotationCoordinates
 * @param {Object} coor coordinate of the field
 * @return {String} notation coordinates string
 */
function getNotationCoordinates(coor) {
	return getXNotationCoordinate(coor.x) + getYNotationCoordinate(coor.y);
}

/**
 * generates pawn capture notation string for a given move
 * @method getPawnCaptureNotation
 * @param {Object} origin coordinate of origin field on the chess board
 * @param {Object} destination coordinate of the destination field on the chess board
 * @return {String} pawn capture notation string
 */
function getPawnCaptureNotation(origin, destination) {
	return getXNotationCoordinate(origin.x) + "x" + getNotationCoordinates(destination);
}

/**
 * converts notation coordinates to the chess board coordinates
 * @method getXYfromNotationCoordinates
 * @param {String} notation coordinates
 * @return {Object} chess board coordinates
 */
function getXYfromNotationCoordinates(coor) {
	
	if(coor == "none") return false;
	
	var x;
	var y;
	
	if(coor[0] == "a") x = 0;
	if(coor[0] == "b") x = 1; 
	if(coor[0] == "c") x = 2; 
	if(coor[0] == "d") x = 3; 
	if(coor[0] == "e") x = 4; 
	if(coor[0] == "f") x = 5; 
	if(coor[0] == "g") x = 6; 
	if(coor[0] == "h") x = 7; 
	
	if(coor[1] == "1") y = 7;
	if(coor[1] == "2") y = 6; 
	if(coor[1] == "3") y = 5; 
	if(coor[1] == "4") y = 4; 
	if(coor[1] == "5") y = 3; 
	if(coor[1] == "6") y = 2; 
	if(coor[1] == "7") y = 1; 
	if(coor[1] == "8") y = 0; 
	
	return {x:x,y:y};
}

/**
 * converts X coordinate of the chess board field to a notation-friendly rank coordinate
 * @method getXNotationCoordinate
 * @param {Number} x X coordinate
 * @return {String} notation-friendly rank coordinate
 */
function getXNotationCoordinate(x) {
	if(x == 0) return "a";
	if(x == 1) return "b";
	if(x == 2) return "c";
	if(x == 3) return "d";
	if(x == 4) return "e";
	if(x == 5) return "f";
	if(x == 6) return "g";
	if(x == 7) return "h";
}

/**
 * converts Y coordinate of the chess board field to a notation-friendly file coordinate
 * @method getYNotationCoordinate
 * @param {Number} y Y coordinate
 * @return {String} notation-friendly file coordinate
 */
function getYNotationCoordinate(y) {
	if(y == 0) return "8";
	if(y == 1) return "7";
	if(y == 2) return "6";
	if(y == 3) return "5";
	if(y == 4) return "4";
	if(y == 5) return "3";
	if(y == 6) return "2";
	if(y == 7) return "1";
}

/**
 * check whatever the position is checkmate for a given side
 * @method isStalemate
 * @param {String} color color of the side, valid values are 'black' and 'white'
 * @return {Boolean} true if position is checkmate, false otherwise
 */
function isMate(color) {
	var legalMoves = [];
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].color == color) {
			legalMoves = legalMoves.concat(board.pieces[i].getLegalMoves());
		}
	}
	
	if(legalMoves.length == 0 && isKingAttacked(color)) return true;
	
	return false;
}

/**
 * check whatever the position is stalemate for a given side
 * @method isStalemate
 * @param {String} color color of the side, valid values are 'black' and 'white'
 * @return {Boolean} true if position is stalemate, false otherwise
 */
function isStalemate(color) {
	var legalMoves = [];
	for(var i = 0; i < board.pieces.length; i++) {
		if(board.pieces[i].color == color) {
			legalMoves.push(board.pieces[i].getLegalMoves());
		}
	}
	
	if(legalMoves.length == 0 && !isKingAttacked(color)) return true;
	
	return false;
}