GameStatus CalculateStatus(Player playerToValidate, bool validateHasAnyValidMoves) { if (_drawn) { return(new GameStatus(GameEvent.Draw, Player.None, _drawReason)); } if (_resigned != Player.None) { return(new GameStatus(GameEvent.Resign, _resigned, _resigned + " resigned")); } var other = ChessUtilities.GetOpponentOf(playerToValidate); if (IsInCheck(playerToValidate)) { if (validateHasAnyValidMoves && !HasAnyValidMoves(playerToValidate)) { return(new GameStatus(GameEvent.Checkmate, other, playerToValidate + " is checkmated")); } return(new GameStatus(GameEvent.Check, other, playerToValidate + " is in check")); } if (validateHasAnyValidMoves && !HasAnyValidMoves(playerToValidate)) { return(new GameStatus(GameEvent.Stalemate, other, "Stalemate")); } return(new GameStatus(GameEvent.None, Player.None, "No special event")); }
void UseGameCreationData(GameCreationData data) { Board = CloneBoard(data.Board); WhoseTurn = data.WhoseTurn; Piece e1 = GetPieceAt(File.E, 1); Piece e8 = GetPieceAt(File.E, 8); Piece a1 = GetPieceAt(File.A, 1); Piece h1 = GetPieceAt(File.H, 1); Piece a8 = GetPieceAt(File.A, 8); Piece h8 = GetPieceAt(File.H, 8); _whiteKingMoved |= (!(e1 is King) || e1.Owner != Player.White); _blackKingMoved |= (!(e8 is King) || e8.Owner != Player.Black); _whiteRookAMoved |= (!(a1 is Rook) || a1.Owner != Player.White || !data.CanWhiteCastleQueenSide); _whiteRookHMoved |= (!(h1 is Rook) || h1.Owner != Player.White || !data.CanWhiteCastleKingSide); _blackRookAMoved |= (!(a8 is Rook) || a8.Owner != Player.Black || !data.CanBlackCastleQueenSide); _blackRookHMoved |= (!(h8 is Rook) || h8.Owner != Player.Black || !data.CanBlackCastleKingSide); if (data.EnPassant != null) { var latestMove = new DetailedMove( new Move(new Square(data.EnPassant.File, data.WhoseTurn == Player.White ? 7 : 2), new Square(data.EnPassant.File, data.WhoseTurn == Player.White ? 5 : 4), ChessUtilities.GetOpponentOf(data.WhoseTurn)), new Pawn(ChessUtilities.GetOpponentOf(data.WhoseTurn)), false, CastlingType.None); _moves.Add(latestMove); } _halfMoveClock = data.HalfMoveClock; _fullMoveNumber = data.FullMoveNumber; }
protected virtual void UseGameCreationData(GameCreationData data) { Board = CloneBoard(data.Board); WhoseTurn = data.WhoseTurn; Piece[] eighthRank = Board[0]; Piece[] firstRank = Board[7]; CanBlackCastleKingSide = CanBlackCastleQueenSide = CanWhiteCastleKingSide = CanWhiteCastleQueenSide = CastlingCanBeLegal; InitialWhiteKingFile = (File)Array.IndexOf(firstRank, new King(Player.White)); InitialBlackKingFile = (File)Array.IndexOf(eighthRank, new King(Player.Black)); if (CastlingCanBeLegal) { CanBlackCastleKingSide = data.CanBlackCastleKingSide; CanBlackCastleQueenSide = data.CanBlackCastleQueenSide; CanWhiteCastleKingSide = data.CanWhiteCastleKingSide; CanWhiteCastleQueenSide = data.CanWhiteCastleQueenSide; } InitialBlackRookFileQueensideCastling = CanBlackCastleQueenSide ? (File)Array.IndexOf(eighthRank, new Rook(Player.Black)) : File.None; InitialBlackRookFileKingsideCastling = CanBlackCastleKingSide ? (File)Array.LastIndexOf(eighthRank, new Rook(Player.Black)) : File.None; InitialWhiteRookFileQueensideCastling = CanWhiteCastleQueenSide ? (File)Array.IndexOf(firstRank, new Rook(Player.White)) : File.None; InitialWhiteRookFileKingsideCastling = CanWhiteCastleKingSide ? (File)Array.LastIndexOf(firstRank, new Rook(Player.White)) : File.None; if (InitialBlackRookFileQueensideCastling == File.None) { CanBlackCastleQueenSide = false; } if (InitialBlackRookFileKingsideCastling == File.None) { CanBlackCastleKingSide = false; } if (InitialWhiteRookFileKingsideCastling == File.None) { CanWhiteCastleKingSide = false; } if (InitialWhiteRookFileQueensideCastling == File.None) { CanWhiteCastleQueenSide = false; } if (data.EnPassant != null) { DetailedMove latestMove = new DetailedMove(new Move(new Position(data.EnPassant.File, data.WhoseTurn == Player.White ? 7 : 2), new Position(data.EnPassant.File, data.WhoseTurn == Player.White ? 5 : 4), ChessUtilities.GetOpponentOf(data.WhoseTurn)), new Pawn(ChessUtilities.GetOpponentOf(data.WhoseTurn)), false, CastlingType.None); _moves.Add(latestMove); } i_halfMoveClock = data.HalfMoveClock; i_fullMoveNumber = data.FullMoveNumber; }
public virtual MoveType ApplyMove(Move move, bool alreadyValidated, out Piece captured) { ChessUtilities.ThrowIfNull(move, "move"); captured = null; if (!alreadyValidated && !IsValidMove(move)) { return(MoveType.Invalid); } MoveType type = MoveType.Move; Piece movingPiece = GetPieceAt(move.OriginalPosition.File, move.OriginalPosition.Rank); Piece capturedPiece = GetPieceAt(move.NewPosition.File, move.NewPosition.Rank); captured = capturedPiece; Piece newPiece = movingPiece; bool isCapture = capturedPiece != null; CastlingType castle = CastlingType.None; if (movingPiece is Pawn) { i_halfMoveClock = 0; PositionDistance pd = new PositionDistance(move.OriginalPosition, move.NewPosition); if (pd.DistanceX == 1 && pd.DistanceY == 1 && GetPieceAt(move.NewPosition) == null) { // en passant isCapture = true; captured = GetPieceAt(move.NewPosition.File, move.OriginalPosition.Rank); SetPieceAt(move.NewPosition.File, move.OriginalPosition.Rank, null); } if (move.NewPosition.Rank == (move.Player == Player.White ? 8 : 1)) { newPiece = MapPgnCharToPiece(move.Promotion.Value, move.Player).AsPromotion(); type |= MoveType.Promotion; } } else if (movingPiece is King) { if (movingPiece.Owner == Player.White) { CanWhiteCastleKingSide = CanWhiteCastleQueenSide = false; } else { CanBlackCastleKingSide = CanBlackCastleQueenSide = false; } if (CastlingCanBeLegal && ((GetPieceAt(move.NewPosition) is Rook && GetPieceAt(move.NewPosition).Owner == move.Player) || ((move.NewPosition.File == File.C || move.NewPosition.File == File.G) && (move.Player == Player.White ? InitialWhiteKingFile : InitialBlackKingFile) == File.E && move.OriginalPosition.File == File.E))) { castle = ApplyCastle(move); type |= MoveType.Castling; isCapture = false; } } else if (movingPiece is Rook) { if (move.Player == Player.White) { if (move.OriginalPosition.File == File.A && move.OriginalPosition.Rank == 1) { CanWhiteCastleQueenSide = false; } else if (move.OriginalPosition.File == File.H && move.OriginalPosition.Rank == 1) { CanWhiteCastleKingSide = false; } } else { if (move.OriginalPosition.File == File.A && move.OriginalPosition.Rank == 8) { CanBlackCastleQueenSide = false; } else if (move.OriginalPosition.File == File.H && move.OriginalPosition.Rank == 8) { CanBlackCastleKingSide = false; } } } if (isCapture) { type |= MoveType.Capture; i_halfMoveClock = 0; if (move.NewPosition.File == File.A && move.NewPosition.Rank == 1) { CanWhiteCastleQueenSide = false; } else if (move.NewPosition.File == File.H && move.NewPosition.Rank == 1) { CanWhiteCastleKingSide = false; } else if (move.NewPosition.File == File.A && move.NewPosition.Rank == 8) { CanBlackCastleQueenSide = false; } else if (move.NewPosition.File == File.H && move.NewPosition.Rank == 8) { CanBlackCastleKingSide = false; } } if (!isCapture && !(movingPiece is Pawn)) { i_halfMoveClock++; if (i_halfMoveClock >= 100) { fiftyMoves = true; } else { fiftyMoves = false; } } if (move.Player == Player.Black) { i_fullMoveNumber++; } if (castle == CastlingType.None) { SetPieceAt(move.NewPosition.File, move.NewPosition.Rank, newPiece); SetPieceAt(move.OriginalPosition.File, move.OriginalPosition.Rank, null); } WhoseTurn = ChessUtilities.GetOpponentOf(move.Player); AddDetailedMove(new DetailedMove(move, movingPiece, isCapture, castle)); return(type); }
public virtual bool IsWinner(Player player) { return(IsCheckmated(ChessUtilities.GetOpponentOf(player))); }
public MoveType ApplyMove(Move move, bool alreadyValidated) { ChessUtilities.ThrowIfNull(move, nameof(move)); if (!alreadyValidated && !IsValidMove(move)) { return(MoveType.Invalid); } var type = MoveType.Move; var movingPiece = GetPieceAt(move.OriginalPosition.File, move.OriginalPosition.Rank); var capturedPiece = GetPieceAt(move.NewPosition.File, move.NewPosition.Rank); var newPiece = movingPiece; var isCapture = capturedPiece != null; var castle = CastlingType.None; if (movingPiece is Pawn) { _halfMoveClock = 0; var pd = new SquareDistance(move.OriginalPosition, move.NewPosition); if (pd.DistanceX == 1 && pd.DistanceY == 1 && GetPieceAt(move.NewPosition) == null) { // en passant isCapture = true; SetPieceAt(move.NewPosition.File, move.OriginalPosition.Rank, null); } if (move.NewPosition.Rank == (move.Player == Player.White ? 8 : 1)) { newPiece = move.Promotion; type |= MoveType.Promotion; } } else if (movingPiece is King) { if (movingPiece.Owner == Player.White) { _whiteKingMoved = true; } else { _blackKingMoved = true; } if (new SquareDistance(move.OriginalPosition, move.NewPosition).DistanceX == 2) { castle = ApplyCastle(move); type |= MoveType.Castling; } } else if (movingPiece is Rook) { if (move.Player == Player.White) { if (move.OriginalPosition.File == File.A && move.OriginalPosition.Rank == 1) { _whiteRookAMoved = true; } else if (move.OriginalPosition.File == File.H && move.OriginalPosition.Rank == 1) { _whiteRookHMoved = true; } } else { if (move.OriginalPosition.File == File.A && move.OriginalPosition.Rank == 8) { _blackRookAMoved = true; } else if (move.OriginalPosition.File == File.H && move.OriginalPosition.Rank == 8) { _blackRookHMoved = true; } } } if (isCapture) { type |= MoveType.Capture; _halfMoveClock = 0; } if (!isCapture && !(movingPiece is Pawn)) { _halfMoveClock++; canClaimDraw = _halfMoveClock == 100; // ahaa so THAT's the HalfMove clock .. number of Plys } if (move.Player == Player.Black) { _fullMoveNumber++; } SetPieceAt(move.NewPosition.File, move.NewPosition.Rank, newPiece); SetPieceAt(move.OriginalPosition.File, move.OriginalPosition.Rank, null); WhoseTurn = ChessUtilities.GetOpponentOf(move.Player); _moves.Add(new DetailedMove(move, movingPiece, isCapture, castle)); return(type); }
public virtual MoveType ApplyMove(Move move, bool alreadyValidated, out Piece captured) { ChessUtilities.ThrowIfNull(move, "move"); captured = null; if (!alreadyValidated && !IsValidMove(move)) { return(MoveType.Invalid); } MoveType type = MoveType.Move; Piece movingPiece = GetPieceAt(move.OriginalPosition.File, move.OriginalPosition.Rank); Piece capturedPiece = GetPieceAt(move.NewPosition.File, move.NewPosition.Rank); captured = capturedPiece; Piece newPiece = movingPiece; enp = "-1"; bool isCapture = capturedPiece != null; CastlingType castle = CastlingType.None; if (movingPiece is Pawn) { i_halfMoveClock = 0; PositionDistance pd = new PositionDistance(move.OriginalPosition, move.NewPosition); if (pd.DistanceX == 1 && pd.DistanceY == 1 && GetPieceAt(move.NewPosition) == null) { // en passant isCapture = true; captured = GetPieceAt(move.NewPosition.File, move.OriginalPosition.Rank); enp = move.NewPosition.File.ToString().ToLower() + move.OriginalPosition.Rank.ToString(); SetPieceAt(move.NewPosition.File, move.OriginalPosition.Rank, null); } if (move.NewPosition.Rank == (move.Player == Player.White ? 8 : 1)) { //get promotion type char PromoteTo; if (move.Promotion == null) { string promote; Console.Write("enter promotion type:"); promote = Console.ReadLine(); switch (promote) { case "queen": PromoteTo = 'Q'; break; case "bishop": PromoteTo = 'B'; break; case "knight": PromoteTo = 'N'; break; case "rook": PromoteTo = 'R'; break; default: PromoteTo = 'Q'; break; } } else { PromoteTo = 'Q'; } newPiece = MapPgnCharToPiece(PromoteTo, move.Player).AsPromotion(); type |= MoveType.Promotion; } } else if (movingPiece is King) { if (movingPiece.Owner == Player.White) { CanWhiteCastleKingSide = CanWhiteCastleQueenSide = false; } else { CanBlackCastleKingSide = CanBlackCastleQueenSide = false; } if (CastlingCanBeLegal && ((GetPieceAt(move.NewPosition) is Rook && GetPieceAt(move.NewPosition).Owner == move.Player) || ((move.NewPosition.File == File.C || move.NewPosition.File == File.G) && (move.Player == Player.White ? InitialWhiteKingFile : InitialBlackKingFile) == File.E && move.OriginalPosition.File == File.E))) { castle = ApplyCastle(move); type |= MoveType.Castling; isCapture = false; } } else if (movingPiece is Rook) { if (move.Player == Player.White) { if (move.OriginalPosition.File == File.A && move.OriginalPosition.Rank == 1) { CanWhiteCastleQueenSide = false; } else if (move.OriginalPosition.File == File.H && move.OriginalPosition.Rank == 1) { CanWhiteCastleKingSide = false; } } else { if (move.OriginalPosition.File == File.A && move.OriginalPosition.Rank == 8) { CanBlackCastleQueenSide = false; } else if (move.OriginalPosition.File == File.H && move.OriginalPosition.Rank == 8) { CanBlackCastleKingSide = false; } } } if (isCapture) { type |= MoveType.Capture; i_halfMoveClock = 0; if (move.NewPosition.File == File.A && move.NewPosition.Rank == 1) { CanWhiteCastleQueenSide = false; } else if (move.NewPosition.File == File.H && move.NewPosition.Rank == 1) { CanWhiteCastleKingSide = false; } else if (move.NewPosition.File == File.A && move.NewPosition.Rank == 8) { CanBlackCastleQueenSide = false; } else if (move.NewPosition.File == File.H && move.NewPosition.Rank == 8) { CanBlackCastleKingSide = false; } } if (!isCapture && !(movingPiece is Pawn)) { i_halfMoveClock++; if (i_halfMoveClock >= 100) { fiftyMoves = true; } else { fiftyMoves = false; } } if (move.Player == Player.Black) { i_fullMoveNumber++; } if (castle == CastlingType.None) { SetPieceAt(move.NewPosition.File, move.NewPosition.Rank, newPiece); SetPieceAt(move.OriginalPosition.File, move.OriginalPosition.Rank, null); } WhoseTurn = ChessUtilities.GetOpponentOf(move.Player); AddDetailedMove(new DetailedMove(move, movingPiece, isCapture, castle)); return(type); }
protected virtual string GetSanForMove(Move move, Piece movingPiece, bool isCapture, CastlingType castle, List <Position> ambiguities) { if (castle == CastlingType.KingSide) { return("O-O"); } if (castle == CastlingType.QueenSide) { return("O-O-O"); } bool needsUnambigFile = false; bool needsUnambigRank = false; if (ambiguities.Count > 0) { foreach (Position amb in ambiguities) { if (amb.Rank == move.OriginalPosition.Rank) { needsUnambigFile = true; } if (amb.File == move.OriginalPosition.File) { needsUnambigRank = true; } } if (!needsUnambigFile && !needsUnambigRank) { needsUnambigFile = true; } } StringBuilder sanBuilder = new StringBuilder(); if (!(movingPiece is Pawn)) { sanBuilder.Append(char.ToUpperInvariant(movingPiece.GetFenCharacter())); } else if (isCapture) { sanBuilder.Append(move.OriginalPosition.File.ToString().ToLowerInvariant()); needsUnambigFile = false; needsUnambigRank = false; } if (needsUnambigFile) { sanBuilder.Append(move.OriginalPosition.File.ToString().ToLowerInvariant()); } if (needsUnambigRank) { sanBuilder.Append(move.OriginalPosition.Rank.ToString()); } if (isCapture) { sanBuilder.Append("x"); } sanBuilder.Append(move.NewPosition.ToString().ToLowerInvariant()); if (move.Promotion.HasValue) { sanBuilder.Append("="); sanBuilder.Append(move.Promotion.Value); } if (IsWinner(ChessUtilities.GetOpponentOf(WhoseTurn))) { sanBuilder.Append("#"); } else if (IsInCheck(WhoseTurn)) { sanBuilder.Append("+"); } return(sanBuilder.ToString()); }