예제 #1
0
        public void UndoMove(uint count)
        {
            while (History.Count > 0 && count > 0)
            {
                var move = History.Peek();

                // undo 'global' information
                Turn           = Chess.InverseColor(move.Color);
                Castling       = move.Castling;
                EnPassantCoord = move.EnPassantCoord;
                HalfMove       = move.HalfMove;
                Move           = move.Move;

                MovePiece(move.To, move.From);

                var flags = move.Flags;
                if (flags.HasFlag(ChessMoveFlag.Promotion))
                {
                    var piece = AddPiece(Turn, ChessPieceType.Pawn, move.To);
                    piece.Guid = move.Guid;
                }

                if (flags.HasFlag(ChessMoveFlag.Capture))
                {
                    var piece = AddPiece(Turn, move.Captured, move.To);
                    piece.Guid = move.CapturedGuid;
                }

                if (flags.HasFlag(ChessMoveFlag.EnPassantCapture))
                {
                    var enPassantFrom = new ChessPieceCoord(move.To);
                    enPassantFrom.MoveOffset(0, move.Color == ChessColor.Black ? 1 : -1);

                    var piece = AddPiece(Turn, ChessPieceType.Pawn, enPassantFrom);
                    piece.Guid = move.CapturedGuid;
                }

                if ((flags & (ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle)) != 0)
                {
                    var castlingTo   = new ChessPieceCoord(move.To);
                    var castlingFrom = new ChessPieceCoord(castlingTo);

                    if (flags.HasFlag(ChessMoveFlag.KingSideCastle))
                    {
                        castlingTo.MoveOffset(1, 0);
                        castlingFrom.MoveOffset(-1, 0);
                    }
                    if (flags.HasFlag(ChessMoveFlag.QueenSideCastle))
                    {
                        castlingTo.MoveOffset(-2, 0);
                        castlingFrom.MoveOffset(1, 0);
                    }

                    MovePiece(castlingTo, castlingFrom);
                }

                History.Pop();
                count--;
            }
        }
예제 #2
0
        public void BuildMove(List <ChessMove> storage, ChessMoveFlag result, ChessColor color, ChessPieceType type, ChessPieceCoord from, ChessPieceCoord to)
        {
            var fromPiece = GetPiece(from);
            var toPiece   = GetPiece(to);

            // AC's Chess implementation doesn't support underpromotion
            var promotion = ChessPieceType.Empty;

            if (fromPiece.Type == ChessPieceType.Pawn && (to.Rank == 1 || to.Rank == 8))
            {
                promotion = ChessPieceType.Queen;
                result   |= ChessMoveFlag.Promotion;
            }

            var captured = ChessPieceType.Empty;

            if (toPiece != null)
            {
                captured = toPiece.Type;
            }
            else if (result.HasFlag(ChessMoveFlag.EnPassantCapture))
            {
                captured = ChessPieceType.Pawn;

                var enPassantCoord = new ChessPieceCoord(to);
                enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 1 : -1);

                toPiece = GetPiece(enPassantCoord);
            }

            storage.Add(new ChessMove(result, color, type, from, to, promotion, captured, Move, HalfMove, Castling, EnPassantCoord, fromPiece.Guid, captured != ChessPieceType.Empty ? toPiece.Guid : new ObjectGuid(0)));
        }
예제 #3
0
        public bool CanAttack(ChessColor attacker, ChessPieceCoord victim)
        {
            for (uint x = 0; x < Chess.BoardSize; x++)
            {
                for (uint y = 0; y < Chess.BoardSize; y++)
                {
                    var piece = Board[x + y * Chess.BoardSize];
                    if (piece == null)
                    {
                        continue;
                    }

                    if (piece.Color != attacker)
                    {
                        continue;
                    }

                    if (piece.CanAttack(victim))
                    {
                        // the knight can jump over other pieces and the pawn can only attack a single space
                        if (piece.Type == ChessPieceType.Knight || piece.Type == ChessPieceType.Pawn)
                        {
                            return(true);
                        }

                        var range = Chess.PieceOffsets[piece.Type];
                        for (var i = 0; i < range.Count; i++)
                        {
                            var from = piece.Coord;
                            var to   = new ChessPieceCoord(from);

                            while (true)
                            {
                                to.MoveOffset(range[i]);
                                if (!to.IsValid())
                                {
                                    break;
                                }

                                var toPiece = GetPiece(to);
                                if (toPiece != null)
                                {
                                    if (to.Equals(victim))
                                    {
                                        return(true);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
예제 #4
0
        public void FinalizeWeenieMove(ChessMoveResult result)
        {
            var move = Logic.GetLastMove();

            Log.Add(move);

            // need to use destination coordinate as Logic has already moved the piece
            var piece = Logic.GetPiece(move.To);

            if (result.HasFlag(ChessMoveResult.OKMoveToEmptySquare))
            {
                MoveWeeniePiece(piece);

                var flags = move.Flags;
                if ((flags & (ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle)) != 0)
                {
                    var castlingTo = new ChessPieceCoord(move.To);
                    if (flags.HasFlag(ChessMoveFlag.KingSideCastle))
                    {
                        castlingTo.MoveOffset(-1, 0);
                    }
                    if (flags.HasFlag(ChessMoveFlag.QueenSideCastle))
                    {
                        castlingTo.MoveOffset(1, 0);
                    }

                    var rookPiece = Logic.GetPiece(castlingTo);
                    Debug.Assert(rookPiece != null);

                    MoveWeeniePiece(rookPiece);
                }
            }
            else if (result.HasFlag(ChessMoveResult.OKMoveToOccupiedSquare))
            {
                AttackWeeniePiece(piece, move.CapturedGuid);
            }
        }
예제 #5
0
        public void InternalMove(ChessMove move)
        {
            var flags   = move.Flags;
            var to      = move.To;
            var from    = move.From;
            var color   = move.Color;
            var opColor = Chess.InverseColor(color);

            MovePiece(from, to);

            if (flags.HasFlag(ChessMoveFlag.EnPassantCapture))
            {
                var enPassantCoord = new ChessPieceCoord(to);
                enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 1 : -1);
                RemovePiece(enPassantCoord);
            }

            if (flags.HasFlag(ChessMoveFlag.Promotion))
            {
                var pawnPiece = GetPiece(to);
                var guid      = pawnPiece.Guid;

                RemovePiece(pawnPiece);

                var queenPiece = AddPiece(color, ChessPieceType.Queen, (uint)to.X, (uint)to.Y);
                queenPiece.Guid = guid;
            }

            if (move.Type == ChessPieceType.King)
            {
                // if we castled, move the rook next to our king
                if ((flags & (ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle)) != 0)
                {
                    var castlingTo   = new ChessPieceCoord(move.To);
                    var castlingFrom = new ChessPieceCoord(castlingTo);

                    if (flags.HasFlag(ChessMoveFlag.KingSideCastle))
                    {
                        castlingTo.MoveOffset(-1, 0);
                        castlingFrom.MoveOffset(1, 0);
                    }
                    if (flags.HasFlag(ChessMoveFlag.QueenSideCastle))
                    {
                        castlingTo.MoveOffset(1, 0);
                        castlingFrom.MoveOffset(-2, 0);
                    }

                    MovePiece(castlingFrom, castlingTo);
                }

                // turn off castling, our king has moved
                Castling[(int)color] = ChessMoveFlag.None;
            }

            // turn off castling if we have moved one of our rooks
            if (Castling[(int)color] != ChessMoveFlag.None)
            {
                DoCastleCheck(color, from);
            }

            // turn off castling if we capture one of the opponent's rooks
            if (Castling[(int)opColor] != ChessMoveFlag.None)
            {
                DoCastleCheck(opColor, from);
            }

            if (flags.HasFlag(ChessMoveFlag.BigPawn))
            {
                var enPassantCoord = new ChessPieceCoord(to);
                //enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 2 : -2);
                enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 1 : -1);
                EnPassantCoord = enPassantCoord;
            }
            else
            {
                EnPassantCoord = null;
            }

            History.Push(move);

            if (color == ChessColor.Black)
            {
                Move++;
            }

            // reset 50 move rule counter if a pawn is moved or a piece is captured
            if (move.Type == ChessPieceType.Pawn ||
                (flags & (ChessMoveFlag.Capture | ChessMoveFlag.EnPassantCapture)) != 0)
            {
                HalfMove = 0;
            }
            else
            {
                HalfMove++;
            }

            Turn = opColor;
        }
예제 #6
0
        public void GenerateMoves(BasePiece piece, bool single, List <ChessMove> storage)
        {
            var color = piece.Color;

            if (piece.Type == ChessPieceType.Pawn)
            {
                // single
                var from = new ChessPieceCoord(piece.Coord);
                var to   = new ChessPieceCoord(from);
                to.MoveOffset(Chess.PawnOffsets[(int)color, 0]);

                if (GetPiece(to) == null)
                {
                    BuildMove(storage, ChessMoveFlag.Normal, color, piece.Type, from, to);

                    // second
                    to = new ChessPieceCoord(from);
                    to.MoveOffset(Chess.PawnOffsets[(int)color, 1]);

                    if (GetPiece(to) == null && from.Rank == (color == ChessColor.White ? 2 : 7))
                    {
                        BuildMove(storage, ChessMoveFlag.BigPawn, color, piece.Type, from, to);
                    }
                }

                // capture
                for (uint i = 2; i < 4; i++)
                {
                    to = new ChessPieceCoord(from);
                    to.MoveOffset(Chess.PawnOffsets[(int)color, i]);
                    if (!to.IsValid())
                    {
                        continue;
                    }

                    var toPiece = GetPiece(to);
                    if (toPiece != null && toPiece.Color != color)
                    {
                        BuildMove(storage, ChessMoveFlag.Capture, color, piece.Type, from, to);
                    }
                    else if (to.Equals(EnPassantCoord))
                    {
                        BuildMove(storage, ChessMoveFlag.EnPassantCapture, color, piece.Type, from, EnPassantCoord);
                    }
                }
            }
            else
            {
                var range = Chess.PieceOffsets[piece.Type];
                for (var i = 0; i < range.Count; i++)
                {
                    var from = piece.Coord;
                    var to   = new ChessPieceCoord(from);

                    while (true)
                    {
                        to.MoveOffset(range[i]);
                        if (!to.IsValid())
                        {
                            break;
                        }

                        var toPiece = GetPiece(to);
                        if (toPiece != null)
                        {
                            if (toPiece.Color != color)
                            {
                                BuildMove(storage, ChessMoveFlag.Capture, color, piece.Type, from, to);
                            }
                            break;
                        }

                        BuildMove(storage, ChessMoveFlag.Normal, color, piece.Type, from, to);

                        // Knights and Kings can't move more than once
                        if (piece.Type == ChessPieceType.Knight || piece.Type == ChessPieceType.King)
                        {
                            break;
                        }
                    }
                }
            }

            // only check for castling during full board generation or for a single king
            if (!single || piece.Type == ChessPieceType.King)
            {
                if ((Castling[(int)color] & ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle) != 0)
                {
                    var king      = GetPiece(color, ChessPieceType.King);
                    var kingCoord = king.Coord;

                    var opColor = Chess.InverseColor(color);

                    if ((Castling[(int)color] & ChessMoveFlag.KingSideCastle) != 0)
                    {
                        var castlingToK = new ChessPieceCoord(kingCoord);    // destination king
                        castlingToK.MoveOffset(2, 0);
                        var castlingToR = new ChessPieceCoord(kingCoord);    // destination rook
                        castlingToR.MoveOffset(1, 0);

                        if (GetPiece(castlingToR) == null &&
                            GetPiece(castlingToK) == null &&
                            !CanAttack(opColor, kingCoord) &&
                            !CanAttack(opColor, castlingToR) &&
                            !CanAttack(opColor, castlingToK))
                        {
                            BuildMove(storage, ChessMoveFlag.KingSideCastle, color, ChessPieceType.King, kingCoord, castlingToK);
                        }
                    }

                    if ((Castling[(int)color] & ChessMoveFlag.QueenSideCastle) != 0)
                    {
                        var castlingToK = new ChessPieceCoord(kingCoord);    // destination king
                        castlingToK.MoveOffset(-2, 0);
                        var castlingToR = new ChessPieceCoord(kingCoord);    // destination rook
                        castlingToR.MoveOffset(-1, 0);
                        var castlingToI = new ChessPieceCoord(kingCoord);    // intermediate
                        castlingToI.MoveOffset(-3, 0);

                        if (GetPiece(castlingToR) == null &&
                            GetPiece(castlingToK) == null &&
                            GetPiece(castlingToI) == null &&
                            !CanAttack(opColor, kingCoord) &&
                            !CanAttack(opColor, castlingToR) &&
                            !CanAttack(opColor, castlingToK))
                        {
                            BuildMove(storage, ChessMoveFlag.QueenSideCastle, color, ChessPieceType.King, kingCoord, castlingToK);
                        }
                    }
                }
            }
        }