API Docs for:
Show:

File: js/classes/pieces/King.js

/**
module contains classes of pieces
@module Pieces
**/ 

/**
* A King class, represents a King piece
* @class King
* @constructor
* @param {} color 	king's color
* @param {} type 	type of the piece, e.g. "King" 
* @param {} X 		x coordinate on the board (0-7), 0 represents 'a' file, 7 represents 'h' file 
* @param {} Y 		y coordinate on the board (0-7), 0 represents 8-th rank, 7 represnts 1-st rank
* @param {} id 		id of the piece
*/
function King(color, type, X, Y, id) {
	
    /**
 	* King's color
 	* @property color
 	* @type String
 	*/
    this.color  = color;
	
	/**
 	* King's type
 	* @property type
 	* @type String
 	*/
    this.type   = type;
	
	/**
 	* x coordinate
 	* @property X
 	* @type Number
 	*/
    this.X      = X;
	
	/**
 	* y coordinate
 	* @property Y
 	* @type Number
 	*/
    this.Y      = Y;
	
	/**
 	* King's ID
 	* @property ID
 	* @type Number
 	*/
	this.ID 	= id;
	
	/**
 	* notation symbol
 	* @property notationName
 	* @type String
 	*/
	this.notationName 	= "K";
	
	/**
     * get relative path to the piece image
     * @method getImageSource
     * @return {String} path to the piece image
     */
    this.getImageSource = function (){
        
        if(this.color == "white") {
            return "images/pieces/wking.png";
        } else {
            return "images/pieces/bking.png";
        }
    }
    
	/**
     * get piece legal moves
     * @method getLegalMoves
     * @return {Array} an array of (x,y) coordinates represents a legal moves for a piece
     */
    this.getLegalMoves = function() {
        var legalMoves = [
            {x:this.X + 1, y:this.Y + 1},
            {x:this.X - 1, y:this.Y - 1},
            {x:this.X + 1, y:this.Y - 1},
            {x:this.X - 1, y:this.Y + 1},
            {x:this.X + 1, y:this.Y},
            {x:this.X - 1, y:this.Y},
            {x:this.X, y:this.Y + 1},
            {x:this.X, y:this.Y - 1}
        ];
        
        for(var i = 0; i < legalMoves.length; i++) {
            if(legalMoves[i].x > 7 || legalMoves[i].y > 7 || legalMoves[i].x < 0 || legalMoves[i].y < 0) {
                legalMoves[i] = null;
            }
        }
        
        legalMoves = legalMoves.clean(null);
        
        parentLoop:
        for(var j = 0; j < legalMoves.length; j++) {
            for(var i = 0; i < board.pieces.length; i++) {
                var p = board.pieces[i];
                var m = legalMoves[j];
                
                if(legalMoves[j] == null) continue parentLoop;
                
                if(p.X == m.x && p.Y == m.y && p.color == this.color) {
                    legalMoves[j] = null;
                }
            }
        }
        
        legalMoves = legalMoves.clean(null); 
        var temp = [];
            
        for(var i = 0; i < board.pieces.length; i++) {
            if(board.pieces[i].color != this.color) {
                temp = temp.concat(board.pieces[i].getCoveredFields());
            }
        }
        
        parentLoop:
        for(var i = 0; i < legalMoves.length; i++) {
            for(var j = 0; j < temp.length; j++) {
                if(legalMoves[i].x == temp[j].x && legalMoves[i].y == temp[j].y) {
                    legalMoves[i] = null;
                    continue parentLoop;
                }
            }
        }
        
        legalMoves = legalMoves.clean(null);
        var coveredFieldsBehind = [];
        
        for(var i = 0; i < board.pieces.length; i++) {
            var p = board.pieces[i];

            if(p.type == "Bishop" && p.color != this.color) {
                var f = getBishopFieldBehind(p.X, p.Y, p.color);
                if(f!=null) coveredFieldsBehind.push(f);
            }

            if(p.type == "Rook" && p.color != this.color) {
                var f = getRookFieldBehind(p.X, p.Y, p.color);
                if(f!=null) coveredFieldsBehind.push(f);
            }

            if(p.type == "Queen" && p.color != this.color) {
                var f = getBishopFieldBehind(p.X, p.Y, p.color);
                if(f!=null) coveredFieldsBehind.push(f);
                var f = getRookFieldBehind(p.X, p.Y, p.color);
                if(f!=null) coveredFieldsBehind.push(f);
            }
        }
        
        parentLoop:
        for(var i = 0; i < legalMoves.length; i++) {
            for(var j = 0; j < coveredFieldsBehind.length; j++) {
                if(legalMoves[i].x == coveredFieldsBehind[j].x && legalMoves[i].y == coveredFieldsBehind[j].y) {
                    legalMoves[i] = null;
                    continue parentLoop;
                }
            }
        }
		
		legalMoves = legalMoves.clean(null);
        
		
		if(this.color == "white" && this.checkCastling("short")) legalMoves.push({x:6,y:7});
		if(this.color == "white" && this.checkCastling("long")) legalMoves.push({x:2,y:7});
		if(this.color == "black" && this.checkCastling("short")) legalMoves.push({x:6,y:0});
		if(this.color == "black" && this.checkCastling("long")) legalMoves.push({x:2,y:0});
		
		legalMoves = legalMoves.clean(null);
		
        return legalMoves;
    }
    
	/**
     * get piece covered fields
     * @method getCoveredFields
     * @return {Array} an array of (x,y) coordinates represents a set of fields, covered by a piece 
     */
    this.getCoveredFields = function() {
        var coveredFields = [
            {x:this.X + 1, y:this.Y + 1},
            {x:this.X - 1, y:this.Y - 1},
            {x:this.X + 1, y:this.Y - 1},
            {x:this.X - 1, y:this.Y + 1},
            {x:this.X + 1, y:this.Y},
            {x:this.X - 1, y:this.Y},
            {x:this.X, y:this.Y + 1},
            {x:this.X, y:this.Y - 1}
        ];
        
        for(var i = 0; i < coveredFields.length; i++) {
            if(coveredFields[i].x > 7 || coveredFields[i].y > 7 || coveredFields[i].x < 0 || coveredFields[i].y < 0) {
                coveredFields[i] = null;
            }
		}

        return coveredFields.clean(null);
    }
	
	/**
     * checks if King has right to castle
     * @method checkCastling
	 * @param {String} direction direction of the castling either 'long' or 'short'
     * @return {Boolean} true if King has right to castle, false otherwise 
     */
	this.checkCastling = function(direction) {
		
		if(this.color == "white") {
			var canCastleLong 	= board.whiteCanCastleLong;
			var canCastleShort 	= board.whiteCanCastleShort;
		} else {
			var canCastleLong 	= board.blackCanCastleLong;
			var canCastleShort 	= board.blackCanCastleShort;
		}
		
		if(canCastleLong == "false" && canCastleShort == "false") return false;
		
		if(direction == "short") {
			if(canCastleShort == "false") return false;
			
			for(var i = 0; i < board.pieces.length; i++) {
				var p = board.pieces[i];
				
				if(this.color == "white") {
					if(p.X == 5 && p.Y == 7 || p.X == 6 && p.Y == 7) {
						return false;
					}
				}
				
				if(this.color == "black") {
					if(p.X == 5 && p.Y == 0 || p.X == 6 && p.Y == 0) {
						return false;
					}
				}
				
				if(p.color != this.color) {
					var cf = p.getCoveredFields();
					for(var j = 0; j < cf.length; j++) {
						if(this.color == "white") {
							if(cf[j].x == 4 && cf[j].y == 7 || cf[j].x == 5 && cf[j].y == 7 || cf[j].x == 6 && cf[j].y == 7) {
								return false;
							}
						} 
						
						if(this.color == "black") {
							if(cf[j].x == 4 && cf[j].y == 0 || cf[j].x == 5 && cf[j].y == 0 || cf[j].x == 6 && cf[j].y == 0) {
								return false;
							}
						}
					}
				}
			}
			
			return true;
		}
		
		if(direction == "long") {
			if(canCastleLong == "false") return false;
			
			for(var i = 0; i < board.pieces.length; i++) {
				var p = board.pieces[i];
				
				if(this.color == "white") {
					if(p.X == 3 && p.Y == 7 || p.X == 2 && p.Y == 7 || p.X == 1 && p.Y == 7) {
						return false;
					}
				}
				
				if(this.color == "black") {
					if(p.X == 3 && p.Y == 0 || p.X == 2 && p.Y == 0 || p.X == 1 && p.Y == 0) {
						return false;
					}
				}
				
				if(p.color != this.color) {
					var cf = p.getCoveredFields();
					for(var j = 0; j < cf.length; j++) {
						if(this.color == "white") {
							if(cf[j].x == 4 && cf[j].y == 7 
							   || cf[j].x == 3 && cf[j].y == 7 
							   || cf[j].x == 2 && cf[j].y == 7 
							   || cf[j].x == 1 && cf[j].y == 7) {
								return false;
							}
						} 
						
						if(this.color == "black") {
							if(cf[j].x == 4 && cf[j].y == 0 
							   || cf[j].x == 3 && cf[j].y == 0 
							   || cf[j].x == 2 && cf[j].y == 0 
							   || cf[j].x == 1 && cf[j].y == 0) {
								return false;
							}
						}
					}
				}
			}
			
			return true;
		}
	}
	
	/**
	 * moves piece to a new field
	 * @method move
	 * @param {Number} x x coordinate of destination
	 * @param {Number} y y coordinate of destination
	 * @return {Object} object represents a summary of the move 
	 */
	this.move = function(x, y) {
		
        if(!confirmMove(x,y,this)) return;
        
        var _isCapture = removeCapturedPiece(x,y);
        
        board.pieces = board.pieces.clean(null);
		
		var origin = {x:this.X,y:this.Y};
		var destination = {x:x,y:y};
        
        for(var i = 0; i < board.pieces.length; i++) {
            if(board.pieces[i].ID == this.ID) {
                board.pieces[i].X = x;
                board.pieces[i].Y = y;
            }
        }
		
		var castling;
        
		if(this.color == "white" && board.whiteCanCastleShort == "true" && x == 6 && y == 7) {
			for(var i = 0; i < board.pieces.length; i++) {
				if(board.pieces[i].X == 7 && board.pieces[i].Y == 7) {
					board.pieces[i].X = 5;
					board.pieces[i].Y = 7;
					castling = "short";
					board.whiteCanCastleShort = "false";
				}
			}
		}
		
		if(this.color == "white" && board.whiteCanCastleLong == "true" && x == 2 && y == 7) {
			for(var i = 0; i < board.pieces.length; i++) {
				if(board.pieces[i].X == 0 && board.pieces[i].Y == 7) {
					board.pieces[i].X = 3;
					board.pieces[i].Y = 7;
					castling = "long";
					board.whiteCanCastleLong = "false";
				}
			}
		}
		
		if(this.color == "black" && board.blackCanCastleShort == "true" && x == 6 && y == 0) {
			for(var i = 0; i < board.pieces.length; i++) {
				if(board.pieces[i].X == 7 && board.pieces[i].Y == 0) {
					board.pieces[i].X = 5;
					board.pieces[i].Y = 0;
					castling = "short";
					board.blackCanCastleShort = "false";
				}
			}
		}
		
		if(this.color == "black" && board.blackCanCastleLong == "true" && x == 2 && y == 0) {
			for(var i = 0; i < board.pieces.length; i++) {
				if(board.pieces[i].X == 0 && board.pieces[i].Y == 0) {
					board.pieces[i].X = 3;
					board.pieces[i].Y = 0;
					castling = "long";
					board.blackCanCastleLong = "false";
				}
			}
		}
		
		if(castling == "long" || castling == "short") {
			board.drawCastling(origin, destination, this);
		} else {
			board.drawMove(origin, destination, this);
		}
		
		board.changeSideToMove();
		
		var targetColor;
		if(this.color == "white") {
			targetColor = "black";
			board.whiteCanCastleLong 	= "false";
			board.whiteCanCastleShort 	= "false";
		}
		else {
			targetColor = "white";
			board.blackCanCastleLong 	= "false";
			board.blackCanCastleShort 	= "false";
		}

		var _isCheck		= isKingAttacked(targetColor);
		var _isMate 		= isMate(targetColor);
		var _isStalemate 	= isStalemate(targetColor);
		
		if(_isCapture) {
			board.drawMoves = 0;
		} else {
			board.drawMoves++;
		}
		
		return getMoveSummary(
			this.notationName, 
			[], 
			origin, 
			destination, 
			castling, 
			_isCapture, 
			_isCheck, 
			_isMate, 
			_isStalemate, 
			"none", 
			"none");
	}
	
	/**
	 * get notation symbol of the piece
	 * @method getNotationSymbol
	 * @return {String} notation symbol
	 */
	this.getNotationSymbol = function() {
		if(this.color == "white") {
			return this.notationName.toUpperCase();
		} else {
			return this.notationName.toLowerCase();
		}
	}
}