/**
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();
}
}
}