API Docs for:
Show:

File: js/classes/pieces/Pawn.js

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

/**
* A Pawn class, represents a Knight piece
* @class Pawn
* @constructor
* @param {} color 	pawn's color
* @param {} type 	type of the piece, e.g. "Pawn" 
* @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 Pawn(color, type, X, Y, id) {
    /**
 	* Pawn's color
 	* @property color
 	* @type String
 	*/
    this.color  = color;
	
	/**
 	* Pawn'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;
	
	/**
 	* Pawn's ID
 	* @property ID
 	* @type Number
 	*/
	this.ID 	= id;
	
	/**
 	* notation symbol
 	* @property notationName
 	* @type String
 	*/
	this.notationName 	= "p";
	
	/**
 	* Boolean flag if piece can be taken en passant
 	* @property canBeTakenEnPassant
 	* @type Boolean
 	*/
	this.canBeTakenEnPassant = false;
	
	/**
     * 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/wpawn.png";
        } else {
            return "images/pieces/bpawn.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 = [];
        var pieceInFront = false;
        
        if(this.color == "white") {
            
            if(this.Y == 6) {
                legalMoves.push({y:5, x:this.X}, {y:4, x:this.X});
            } else {
                legalMoves.push({y:this.Y - 1, x:this.X});
				for(var i = 0; i < board.pieces.length; i++) {
					var p = board.pieces[i];
					if(p.color != this.color && p.canBeTakenEnPassant && Math.abs(p.X - this.X) == 1 && p.Y == 3 && this.Y == 3) {
						legalMoves.push({x:p.X,y:2});
					}
				}
            }
            
            parentLoop:
            for(i = 0; i < legalMoves.length; i++) {
                for(var j = 0; j < board.pieces.length; j++) {
                    var p = board.pieces[j];
                    var m = legalMoves[i];
                    if(p.X == m.x && p.Y == m.y) {
                        legalMoves[i] = null;
                        continue parentLoop;
                    }
                }
            }
            
            legalMoves = legalMoves.clean(null);
			
			for(i = 0; i < legalMoves.length; i++) {
                for(var j = 0; j < board.pieces.length; j++) {
                    var p = board.pieces[j];
                    var m = legalMoves[i];
					
					if(this.Y == 6 && m.y == 4 && p.Y == 5 && p.X == this.X) {
						legalMoves[i] = null;
						break;
					}
                }
            }
			
			legalMoves = legalMoves.clean(null);
            
            for(var i=0; i<board.pieces.length; i++) {
                var p = board.pieces[i];
                if(p.color == "white") continue;
                if(p.Y == this.Y-1 && p.X == this.X-1) {
                    legalMoves.push({x:p.X, y:p.Y});
                }
                if(p.Y == this.Y-1 && p.X == this.X+1) {
                    legalMoves.push({x:p.X, y:p.Y});
                }
            }
        }

        if(this.color == "black") {
        
            if(this.Y == 1) {
                legalMoves.push({y:2, x:this.X}, {y:3, x:this.X});
            } else {
                legalMoves.push({y:this.Y + 1, x:this.X});
				for(var i = 0; i < board.pieces.length; i++) {
					var p = board.pieces[i];
					if(p.color != this.color && p.canBeTakenEnPassant && Math.abs(p.X - this.X) == 1 && p.Y == 4 && this.Y == 4) {
						legalMoves.push({x:p.X,y:5});
					}
				}
            }
            
            parentLoop:
            for(i = 0; i < legalMoves.length; i++) {
                for(var j = 0; j < board.pieces.length; j++) {
                    var p = board.pieces[j];
                    var m = legalMoves[i];
                    if(p.X == m.x && p.Y == m.y) {
                        legalMoves[i] = null;
                        continue parentLoop;
                    }
                }
            }
			
			legalMoves = legalMoves.clean(null);
			
			for(i = 0; i < legalMoves.length; i++) {
                for(var j = 0; j < board.pieces.length; j++) {
                    var p = board.pieces[j];
                    var m = legalMoves[i];
					
					if(this.Y == 1 && m.y == 3 && p.Y == 2 && p.X == this.X) {
						legalMoves[i] = null;
						break;
					}
                }
            }
            
            legalMoves = legalMoves.clean(null);
            
            for(var i=0; i<board.pieces.length; i++) {
                var p = board.pieces[i];
                if(p.color == "black") continue;
                if(p.Y == this.Y+1 && p.X == this.X-1) {
                    legalMoves.push({x:p.X, y:p.Y});
                }
                if(p.Y == this.Y+1 && p.X == this.X+1) {
                    legalMoves.push({x:p.X, y:p.Y});
                }
            }
        }
        
        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);
        return preventCheck(this, 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() {
        
        coveredFields = [];
        
        if(this.color == "white") {
            coveredFields.push({x:this.X + 1,y:this.Y - 1});
            coveredFields.push({x:this.X - 1,y:this.Y - 1});
        }
        
        if(this.color == "black") {
            coveredFields.push({x:this.X + 1,y:this.Y + 1});
            coveredFields.push({x:this.X - 1,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);
    }
	
	/**
	 * moves piece to a new field
	 * @method move
	 * @param {Number} x x coordinate of destination
	 * @param {Number} y y coordinate of destination
	 * @param {String} pc represents a promotion choice in case of pawn promotion. 
	 * Valid values are 'Q' for Queen,'R' for Rook,'N' for Knight,'B' for Bishop or null in case pawn does not promote on that move.
	 * @return {Object} object represents a summary of the move 
	 */
	this.move = function(x,y,pc) {

		var origin = {x:this.X,y:this.Y};
		var destination = {x:x,y:y};
		
        if(!confirmMove(x,y,this)) return;
		
		if(this.type == "Pawn" && this.Y == 6 && y == 4 && this.color == "white") {
			this.canBeTakenEnPassant = true;
		}
		
		if(this.type == "Pawn" && this.Y == 1 && y == 3 && this.color == "black") {
			this.canBeTakenEnPassant = true;
		}
		
		var p = null;
		for(var i = 0; i < board.pieces.length; i++) {
			if(board.pieces[i].X == x && board.pieces[i].Y == y) {
				p = board.pieces[i];
			}
		}
		
		enPassant = false;
		if(this.X != x && p == null) {
			for(var i = 0; i < board.pieces.length; i++) {
				if(board.pieces[i].color != this.color && board.pieces[i].canBeTakenEnPassant) {
					board.pieces[i] = null;
					enPassant = true;
				}
			}
		}
		
		board.pieces = board.pieces.clean(null);
		
		for(var i = 0; i < board.pieces.length; i++) {
			if(board.pieces[i].color != this.color && board.pieces[i].type == "Pawn") 
				board.pieces[i].canBeTakenEnPassant = false;
		}

		_isCapture = removeCapturedPiece(x,y);

		board.pieces = board.pieces.clean(null);
		
		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;
			}
		}
		
		if(pc != "none") {
			for(var i = 0; i < board.pieces.length; i++) {
				if(board.pieces[i].ID == this.ID) {
					board.pieces[i] = null;
					break;
				}
			}
			
			board.pieces = board.pieces.clean(null);
			
			var newId = 0;
			for(var i = 0; i < board.pieces.length; i++) {
				if(board.pieces[i].ID > newId) 
					newId = board.pieces[i].ID;
			}
			
			var newPiece;
			
			if(pc == "Q") {
				newPiece = new Queen(this.color, "Queen", this.X, this.Y, newId + 1);
				board.pieces.push(newPiece);
			}
			
			if(pc == "R") {
				newPiece = new Rook(this.color, "Rook", this.X, this.Y, newId + 1);
				board.pieces.push(newPiece);
			}
			
			if(pc == "N") {
				newPiece = new Knight(this.color, "Knight", this.X, this.Y, newId + 1);
				board.pieces.push(newPiece);
			}
			
			if(pc == "B") {
				newPiece = new Bishop(this.color, "Bishop", this.X, this.Y, newId + 1);
				board.pieces.push(newPiece);
			}
		}
		
		if(enPassant) {
			board.drawEnpassant(origin, destination, this)
		} else {
			if(pc!="none") {
				board.drawMove(origin, destination, newPiece);
			} else {
				board.drawMove(origin, destination, this);
			}
		}

		board.changeSideToMove();
		
		var targetColor;
		if(this.color == "white") 
			targetColor = "black";
		else
			targetColor = "white";
		
		var _isCheck		= isKingAttacked(targetColor);
		var _isMate 		= isMate(targetColor);
		var _isStalemate 	= isStalemate(targetColor);
		var _enPassant;
		
		if(this.canBeTakenEnPassant) {
			_enPassant = getNotationCoordinates({x:this.X, y:this.Y});
		} else {
			_enPassant = "none";
		}
		
		board.drawMoves = 0;
		
		return getMoveSummary(
			this.notationName,
			[],
			origin, 
			destination,
			"none",
			_isCapture,  
			_isCheck, 
			_isMate, 
			_isStalemate, 
			pc,
			_enPassant);
	}
	
	/**
	 * moves piece to a new field
	 * @method isPromotionMove
	 * @param {Object} chessCoor an object represents the coordinates of the field where pawn promotes
	 * @return {Boolean} true in case the move is promotion of a pawn, false otherwise 
	 */
	this.isPromotionMove = function(chessCoor) {
		var found = false;
		if(this.color == "white" && chessCoor.y == 0) {
			var legalMoves = this.getLegalMoves();

			for(var i = 0; i < legalMoves.length; i++) {
				if(legalMoves[i].x == chessCoor.x && legalMoves[i].y == chessCoor.y) {
					found = true;
					break;
				}
			}
		}
		
		if(this.color == "black" && chessCoor.y == 7) {
			var legalMoves = this.getLegalMoves();

			for(var i = 0; i < legalMoves.length; i++) {
				if(legalMoves[i].x == chessCoor.x && legalMoves[i].y && chessCoor.y) {
					found = true;
					break;
				}
			}
		}
		
		return found;
	}
	
	/**
	 * 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();
		}
	}
}