// try to do a movement of piece public MovementResult MovePiece(char column, int row, char targetColumn, int targetRow) { MovementResult result = new MovementResult(); var selectPiece = GetPiece(column, row); // check if there is a piece at start position if (selectPiece == null) { result.IsSuccess = false; result.Description = String.Format("No piece is present at position {0}{1}", column, row.ToString()); return(result); } var targetPiece = GetPiece(targetColumn, targetRow); // check it is a valid movement for piece (rules piece validator) if (!selectPiece.IsValidMovement( (targetPiece != null && !selectPiece.ChessColor.Equals(targetPiece.ChessColor)), row - 1, Columns[column], targetRow - 1, Columns[targetColumn])) { result.IsSuccess = false; result.Description = String.Format("The {0} {1} at position {2}{3} cannot move to {4}{5}", selectPiece.ChessColor.ToString(), selectPiece.GetType().Name, column, row.ToString(), targetColumn, targetRow.ToString()); return(result); } // check if the path is free if piece is not a knight if (!(selectPiece is Knight) && !checkIfPathIsFree(column, row, targetColumn, targetRow)) { result.IsSuccess = false; result.Description = String.Format("The path from {0}{1} to {2}{3} for {4}{5} is not free.", column, row.ToString(), targetColumn, targetRow.ToString(), selectPiece.ChessColor.ToString(), selectPiece.GetType().Name); return(result); } // check if target position there is already present a piece with same color if (targetPiece != null && selectPiece.ChessColor.Equals(targetPiece.ChessColor)) { result.IsSuccess = false; result.Description = String.Format("There is already present a {0} piece at position {1}{2}", selectPiece.ChessColor.ToString(), targetColumn, targetRow); return(result); } // set result information after capture result.Capture = (targetPiece != null && !selectPiece.ChessColor.Equals(targetPiece.ChessColor)); if (result.Capture) { result.CapturedPiece = targetPiece; } // change position of piece putPiece(selectPiece, targetColumn, targetRow); clearBoardPosition(column, row); return(result); }
private MovementResult MovePiece(char column, int row, char targetColumn, int targetRow, bool forTest) { MovementResult result = new MovementResult(); var selectPiece = GetPiece(column, row); // check if there is a piece at start position if (selectPiece == null) { result.IsSuccess = false; result.Description = String.Format("No piece is present at position {0}{1}", column, row.ToString()); return(result); } Piece targetPiece = null; var isEnPassant = EnPassant != null && selectPiece is Pawn && targetColumn == EnPassant.Item1 && targetRow == EnPassant.Item2; if (!isEnPassant) { targetPiece = GetPiece(targetColumn, targetRow); } else { targetPiece = GetPiece(targetColumn, row); } // check it is a valid movement for piece (rules piece validator) if (!selectPiece.IsValidMovement( (targetPiece != null && !selectPiece.ChessColor.Equals(targetPiece.ChessColor)), row - 1, Columns[column], targetRow - 1, Columns[targetColumn])) { result.IsSuccess = false; result.Description = String.Format("The {0} {1} at position {2}{3} cannot move to {4}{5}", selectPiece.ChessColor.ToString(), selectPiece.GetType().Name, column, row.ToString(), targetColumn, targetRow.ToString()); return(result); } // check if the path is free if piece is not a knight if (!(selectPiece is Knight) && !checkIfPathIsFree(column, row, targetColumn, targetRow)) { result.IsSuccess = false; result.Description = String.Format("The path from {0}{1} to {2}{3} for {4}{5} is not free.", column, row.ToString(), targetColumn, targetRow.ToString(), selectPiece.ChessColor.ToString(), selectPiece.GetType().Name); return(result); } // check if target position there is already present a piece with same color if (targetPiece != null && selectPiece.ChessColor.Equals(targetPiece.ChessColor)) { result.IsSuccess = false; result.Description = String.Format("There is already present a {0} piece at position {1}{2}", selectPiece.ChessColor.ToString(), targetColumn, targetRow); return(result); } //En passant done if (isEnPassant && !forTest) { clearBoardPosition(targetColumn, row); } // set result information after ate result.Ate = (targetPiece != null && !selectPiece.ChessColor.Equals(targetPiece.ChessColor)); if (result.Ate) { result.AtePiece = targetPiece; } // set EnPassant Information EnPassant = null; if ((selectPiece is Pawn) && (Math.Abs(row - targetRow) == 2)) { //En passant possibilities var pieceLeft = TryGetPiece(Columns[targetColumn], targetRow); var pieceRigth = TryGetPiece(Columns[targetColumn] + 2, targetRow); if ((pieceLeft != null && pieceLeft.ChessColor != selectPiece.ChessColor && pieceLeft is Pawn) || (pieceRigth != null && pieceRigth.ChessColor != selectPiece.ChessColor && pieceRigth is Pawn)) { EnPassant = new Tuple <char, int>(targetColumn, (targetRow + row) / 2); } } //Castling rules bool isCastling = false; if ((selectPiece is King) && Math.Abs(Columns[column] - Columns[targetColumn]) == 2) { //1-The king should not have moved yet var king = (King)selectPiece; if (king.HasAlreadyMoved || !(column == 'E' && (row == 1 || row == 8))) { result.IsSuccess = false; result.Description = String.Format("You cannot do the Castling because your king has already moved."); return(result); } //2-The Rook should not have moved yet either var rookColumn = (targetColumn == 'G') ? 'H' : 'A'; var pieceFound = GetPiece(rookColumn, targetRow); if (pieceFound == null || pieceFound.ChessColor != king.ChessColor || !(pieceFound is Rook)) { result.IsSuccess = false; result.Description = String.Format("You cannot do the Castling because there is no Rook at position {0}{1}.", rookColumn, targetRow); return(result); } var goodRook = (Rook)pieceFound; if (goodRook.HasAlreadyMoved) { result.IsSuccess = false; result.Description = String.Format("You cannot do the Castling as your rook has already moved at position {0}{1}.", rookColumn, targetRow); return(result); } //3-The King should not be chess or passing on a echec position var canMoveOnTheKing = CheckKingEchec(king.ChessColor); if (canMoveOnTheKing != null) { result.IsSuccess = false; result.Description = String.Format("You cannot do the Castling because you are echec {0}{1}.", canMoveOnTheKing.Item1, canMoveOnTheKing.Item2); return(result); } //4-Can do one step : var oneStepColumn = (targetColumn == 'G') ? 'F' : 'D'; var canDoOne = this.MovePiece(column, row, oneStepColumn, targetRow); if (!canDoOne.IsSuccess) { result.IsSuccess = false; result.Description = String.Format("You cannot do the Castling because you would be echec at the position {0}{1}.", oneStepColumn, targetRow); return(result); } else { //One step is posible, so rollback, and test two step : PutPiece(king, column, row); clearBoardPosition(oneStepColumn, row); king.HasAlreadyMoved = false; isCastling = true; } } // change position of piece if (!forTest) { PutPiece(selectPiece, targetColumn, targetRow); clearBoardPosition(column, row); //Pawn reach the opposite side, can be promoted if (selectPiece is Pawn && (targetRow == 1 || targetRow == 8)) { PawnPromoted = true; PawnPromotedColor = selectPiece.ChessColor; } // check if the move does not make our king in chess Tuple <char, int> pieceWitchMakeChess = CheckKingEchec(selectPiece.ChessColor); if (pieceWitchMakeChess != null) { //RollBack PutPiece(selectPiece, column, row); clearBoardPosition(targetColumn, targetRow); PawnPromoted = false; if (result.Ate == true) { var pieceEaten = result.AtePiece; this.PutPiece(pieceEaten, targetColumn, targetRow); result.AtePiece = null; result.Ate = false; } result.IsSuccess = false; result.Description = String.Format("Your king is in echec from the piece {0} ({1}{2}).", selectPiece.GetType().Name, pieceWitchMakeChess.Item1, pieceWitchMakeChess.Item2); return(result); } if (selectPiece is IHasAlreadyMoved) { ((IHasAlreadyMoved)selectPiece).HasAlreadyMoved = true; //TODO : Move the rook in case of castling if (isCastling) { var rookColumnOrigin = (targetColumn == 'G') ? 'H' : 'A'; var rookColumnTarget = (targetColumn == 'G') ? 'F' : 'D'; var pieceFound = GetPiece(rookColumnOrigin, row); PutPiece(pieceFound, rookColumnTarget, row); clearBoardPosition(rookColumnOrigin, row); } } } return(result); }