コード例 #1
0
        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);
        }
コード例 #2
0
ファイル: ChessPiece.cs プロジェクト: gunr2171/Chess.NET
 public ChessPiece(Piece piece, Player player)
 {
     Piece = piece;
     Player = player;
 }
コード例 #3
0
        protected virtual GameCreationData FenStringToGameCreationData(string fen)
        {
            Dictionary <char, Piece> fenMappings = FenMappings;

            string[] parts = fen.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (!AllowedFenPartsLength.Contains(parts.Length))
            {
                throw new ArgumentException("The FEN string has too much, or too few, parts.");
            }
            Piece[][] board = new Piece[8][];
            string[]  rows  = parts[0].Split('/');
            if (!ValidFenBoardRows.Contains(rows.Length))
            {
                throw new ArgumentException("The board in the FEN string has an invalid number of rows.");
            }
            GameCreationData data = new GameCreationData();

            data.Board = InterpretBoardOfFen(parts[0]);

            if (parts[1] == "w")
            {
                data.WhoseTurn = Player.White;
            }
            else if (parts[1] == "b")
            {
                data.WhoseTurn = Player.Black;
            }
            else
            {
                throw new ArgumentException("Expected `w` or `b` for the active player in the FEN string.");
            }

            if (parts[2].Contains("K"))
            {
                data.CanWhiteCastleKingSide = true;
            }
            else
            {
                data.CanWhiteCastleKingSide = false;
            }

            if (parts[2].Contains("Q"))
            {
                data.CanWhiteCastleQueenSide = true;
            }
            else
            {
                data.CanWhiteCastleQueenSide = false;
            }

            if (parts[2].Contains("k"))
            {
                data.CanBlackCastleKingSide = true;
            }
            else
            {
                data.CanBlackCastleKingSide = false;
            }

            if (parts[2].Contains("q"))
            {
                data.CanBlackCastleQueenSide = true;
            }
            else
            {
                data.CanBlackCastleQueenSide = false;
            }

            if (parts[3] == "-")
            {
                data.EnPassant = null;
            }
            else
            {
                Position ep = new Position(parts[3]);
                if ((data.WhoseTurn == Player.White && (ep.Rank != 6 || !(data.Board[3][(int)ep.File] is Pawn))) ||
                    (data.WhoseTurn == Player.Black && (ep.Rank != 3 || !(data.Board[4][(int)ep.File] is Pawn))))
                {
                    throw new ArgumentException("Invalid en passant field in FEN.");
                }
                data.EnPassant = ep;
            }

            int halfmoveClock;

            if (int.TryParse(parts[4], out halfmoveClock))
            {
                data.HalfMoveClock = halfmoveClock;
            }
            else
            {
                throw new ArgumentException("Halfmove clock in FEN is invalid.");
            }

            int fullMoveNumber;

            if (int.TryParse(parts[5], out fullMoveNumber))
            {
                data.FullMoveNumber = fullMoveNumber;
            }
            else
            {
                throw new ArgumentException("Fullmove number in FEN is invalid.");
            }

            return(data);
        }
コード例 #4
0
 protected virtual void SetPieceAt(File file, int rank, Piece piece)
 {
     Board[8 - rank][(int)file] = piece;
 }
コード例 #5
0
        public virtual bool IsInCheck(Player player)
        {
            if (player == Player.None)
            {
                throw new ArgumentException("IsInCheck: Player.None is an invalid argument.");
            }
            Cache <bool> cache = player == Player.White ? inCheckCacheWhite : inCheckCacheBlack;

            if (cache.CachedAt == Moves.Count)
            {
                return(cache.Value);
            }

            Position kingPos = new Position(File.None, -1);

            for (int r = 1; r <= Board.Length; r++)
            {
                for (int f = 0; f < Board[8 - r].Length; f++)
                {
                    Piece curr = GetPieceAt((File)f, r);
                    if (curr is King && curr.Owner == player)
                    {
                        kingPos = new Position((File)f, r);
                        break;
                    }
                }
                if (kingPos != new Position(File.None, -1))
                {
                    break;
                }
            }

            if (kingPos.File == File.None)
            {
                return(cache.UpdateCache(false, Moves.Count));
            }

            for (int r = 1; r <= Board.Length; r++)
            {
                for (int f = 0; f < Board[8 - r].Length; f++)
                {
                    Piece curr = GetPieceAt((File)f, r);
                    if (curr == null)
                    {
                        continue;
                    }
                    Player      p     = curr.Owner;
                    Move        move  = new Move(new Position((File)f, r), kingPos, p);
                    List <Move> moves = new List <Move>();
                    if (curr is Pawn && ((move.NewPosition.Rank == 8 && move.Player == Player.White) || (move.NewPosition.Rank == 1 && move.Player == Player.Black)))
                    {
                        moves.Add(new Move(move.OriginalPosition, move.NewPosition, move.Player, 'Q'));
                        moves.Add(new Move(move.OriginalPosition, move.NewPosition, move.Player, 'R'));
                        moves.Add(new Move(move.OriginalPosition, move.NewPosition, move.Player, 'B'));
                        moves.Add(new Move(move.OriginalPosition, move.NewPosition, move.Player, 'N'));
                        moves.Add(new Move(move.OriginalPosition, move.NewPosition, move.Player, 'K'));
                    }
                    else
                    {
                        moves.Add(move);
                    }
                    foreach (Move m in moves)
                    {
                        if (IsValidMove(m, false, false))
                        {
                            return(cache.UpdateCache(true, Moves.Count));
                        }
                    }
                }
            }
            return(cache.UpdateCache(false, Moves.Count));
        }
コード例 #6
0
ファイル: ChessGame.cs プロジェクト: ProgramFOX/Chess.NET
 protected virtual void SetPieceAt(File file, int rank, Piece piece)
 {
     Board[8 - rank][(int)file] = piece;
 }
コード例 #7
0
ファイル: ChessGame.cs プロジェクト: ProgramFOX/Chess.NET
        protected virtual GameCreationData FenStringToGameCreationData(string fen)
        {
            Dictionary<char, Piece> fenMappings = FenMappings;
            string[] parts = fen.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (!AllowedFenPartsLength.Contains(parts.Length)) throw new ArgumentException("The FEN string has too much, or too few, parts.");
            Piece[][] board = new Piece[8][];
            string[] rows = parts[0].Split('/');
            if (rows.Length != 8) throw new ArgumentException("The board in the FEN string does not have 8 rows.");
            GameCreationData data = new GameCreationData();
            for (int i = 0; i < 8; i++)
            {
                string row = rows[i];
                Piece[] currentRow = new Piece[8] { null, null, null, null, null, null, null, null };
                int j = 0;
                foreach (char c in row)
                {
                    if (char.IsDigit(c))
                    {
                        j += (int)char.GetNumericValue(c);
                        continue;
                    }
                    if (!fenMappings.ContainsKey(c)) throw new ArgumentException("The FEN string contains an unknown piece.");
                    currentRow[j] = fenMappings[c];
                    j++;
                }
                if (j != 8)
                {
                    throw new ArgumentException("Not enough pieces provided for a row in the FEN string.");
                }
                board[i] = currentRow;
            }
            data.Board = board;

            if (parts[1] == "w")
            {
                data.WhoseTurn = Player.White;
            }
            else if (parts[1] == "b")
            {
                data.WhoseTurn = Player.Black;
            }
            else
            {
                throw new ArgumentException("Expected `w` or `b` for the active player in the FEN string.");
            }

            if (parts[2].Contains('K')) data.CanWhiteCastleKingSide = true;
            else data.CanWhiteCastleKingSide = false;

            if (parts[2].Contains('Q')) data.CanWhiteCastleQueenSide = true;
            else data.CanWhiteCastleQueenSide = false;

            if (parts[2].Contains('k')) data.CanBlackCastleKingSide = true;
            else data.CanBlackCastleKingSide = false;

            if (parts[2].Contains('q')) data.CanBlackCastleQueenSide = true;
            else data.CanBlackCastleQueenSide = false;

            if (parts[3] == "-") data.EnPassant = null;
            else
            {
                Position ep = new Position(parts[3]);
                if ((data.WhoseTurn == Player.White && (ep.Rank != 6 || !(data.Board[3][(int)ep.File] is Pawn))) ||
                    (data.WhoseTurn == Player.Black && (ep.Rank != 3 || !(data.Board[4][(int)ep.File] is Pawn))))
                {
                    throw new ArgumentException("Invalid en passant field in FEN.");
                }
                data.EnPassant = ep;
            }

            int halfmoveClock;
            if (int.TryParse(parts[4], out halfmoveClock))
            {
                data.HalfMoveClock = halfmoveClock;
            }
            else
            {
                throw new ArgumentException("Halfmove clock in FEN is invalid.");
            }

            int fullMoveNumber;
            if (int.TryParse(parts[5], out fullMoveNumber))
            {
                data.FullMoveNumber = fullMoveNumber;
            }
            else
            {
                throw new ArgumentException("Fullmove number in FEN is invalid.");
            }

            return data;
        }
コード例 #8
0
ファイル: ChessGame.cs プロジェクト: ProgramFOX/Chess.NET
 public ChessGame(Piece[][] board, Player whoseTurn)
 {
     Board = CloneBoard(board);
     _moves = new List<DetailedMove>();
     WhoseTurn = 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);
     CanBlackCastleKingSide = CanBlackCastleQueenSide = CanWhiteCastleKingSide = CanWhiteCastleQueenSide = CastlingCanBeLegal;
     if (CastlingCanBeLegal)
     {
         if (!(e1 is King) || e1.Owner != Player.White)
             CanWhiteCastleKingSide = CanWhiteCastleQueenSide = false;
         if (!(e8 is King) || e8.Owner != Player.Black)
             CanBlackCastleKingSide = CanBlackCastleQueenSide = false;
         if (!(a1 is Rook) || a1.Owner != Player.White)
             CanWhiteCastleQueenSide = false;
         if (!(h1 is Rook) || h1.Owner != Player.White)
             CanWhiteCastleKingSide = false;
         if (!(a8 is Rook) || a8.Owner != Player.Black)
             CanBlackCastleQueenSide = false;
         if (!(h8 is Rook) || h8.Owner != Player.Black)
             CanBlackCastleKingSide = false;
     }
 }
コード例 #9
0
ファイル: ChessGame.cs プロジェクト: ProgramFOX/Chess.NET
 protected static Piece[][] CloneBoard(Piece[][] originalBoard)
 {
     ChessUtilities.ThrowIfNull(originalBoard, "originalBoard");
     Piece[][] newBoard = new Piece[originalBoard.Length][];
     for (int i = 0; i < originalBoard.Length; i++)
     {
         newBoard[i] = new Piece[originalBoard[i].Length];
         Array.Copy(originalBoard[i], newBoard[i], originalBoard[i].Length);
     }
     return newBoard;
 }