public ValidateMoveResult CanMove(ChessBoard board, string move, PlayerTypeEnum player, string lastMoveNotation) { Tuple<string, string> breakdown = NotationHelper.Breakdown(move); string source = breakdown.Item1; string destination = breakdown.Item2; bool playerInCheck = IsInCheck(player, board, lastMoveNotation).Item1; ValidateMoveResult canMoveResult = CanMove(board, source, destination, player, lastMoveNotation, playerInCheck); if (canMoveResult.Success) { // pawn to queen swap ChessPiece sourceBeforeSimulate = board.Get(source); bool pawnSwap = sourceBeforeSimulate != null && sourceBeforeSimulate.Type == PieceTypeEnum.Pawn && (sourceBeforeSimulate.Direction == -1 ? (int.Parse(destination[1].ToString()) == 8) : (int.Parse(destination[1].ToString()) == 1)); string swap = pawnSwap ? destination : null; canMoveResult.Swap = swap; ChessBoard boardAfterMove = board.SimulateMoves(move, canMoveResult.TakenPiece, swap); // did player move into check? var movedIntoCheckResult = IsInCheck(player, boardAfterMove, lastMoveNotation); if (movedIntoCheckResult.Item1) { canMoveResult.Success = false; return canMoveResult.SetMessage("cannot move into check."); } // did player put opponent in check? var isOpponentInCheckResult = IsInCheck(GetOppositePlayer(player), boardAfterMove, lastMoveNotation); bool isOpponentInCheck = isOpponentInCheckResult.Item1; canMoveResult.MoveType = isOpponentInCheck ? MoveTypeEnum.Check : MoveTypeEnum.Normal; // if player checked opponent, can opponent get out of check? if not, check mate if (isOpponentInCheck) { string opponentKingNotation = boardAfterMove.GetKing(GetOppositePlayer(player)); Tuple<int, int> opponentKingTuple = NotationHelper.Translate(opponentKingNotation); // can checked king move out of check? bool canMoveOutOfCheck = CanMoveOutOfCheck(player, lastMoveNotation, boardAfterMove, opponentKingNotation, opponentKingTuple); // can opponent kill piece that put king in check? is still in check afterwards? bool canTakedownAttacker = false; if (!canMoveOutOfCheck) canTakedownAttacker = CanTakedownAttackers(player, lastMoveNotation, boardAfterMove, isOpponentInCheckResult.Item2); // can block path of piece that put king in check? (brute force method) bool canBlockPathOfAttackers = false; if (!canMoveOutOfCheck && !canTakedownAttacker) canBlockPathOfAttackers = CanMoveIntoAttackersPath(player, lastMoveNotation, boardAfterMove, isOpponentInCheckResult.Item2, opponentKingTuple); if (!canMoveOutOfCheck && !canTakedownAttacker && !canBlockPathOfAttackers) canMoveResult.MoveType = MoveTypeEnum.Checkmate; } } return canMoveResult; }