示例#1
0
        /*
         * Determines if the last move caused the game to end
         *
         * First, check if the king is in check, and store it in a boolean variable.
         *
         * If the king is in check, check if the attack is preventable. This is done
         * by seeing it the king can either move away safely or can neutralize all
         * attacks (both the primary attack and discoveryCheck if it occured). If the
         * king is in check and the conditions checking if the attempted capture
         * is preventable, checkmate has occured, otherwise the game is not over and the
         * King is simply in check.
         *
         * If the king is not in check, determine if any of the various draw conditions are
         * met, including by repetition, redundancy (x moves without a capture or pawn movement),
         * stalemate (where a player can not make a legal move) and by material (where neither side
         * has enough material to checkmate).
         *
         * If none of those conditions are met, the game can still be played, and is
         * considered to have normal status.
         */
        private void IsGameOver(ChessMove.MoveStatusCodes moveType, BoardSquare directAttacker)
        {
            // Check if king is in check (discovered, normal)
            // Be sure to account for rook when castled, removed pawn in en passant

            // If one or the other, check for blocks, capture, move out of way
            // If both, check move out of way
            // If neither, check other pieces can move (stalemate)
            // Check draw by repetition, inaction (no capture/movement), and material

            // Set gameStatus internal variable as appropriate

            BoardSquare currKingPos = this.kingPos[(int)(whiteTurn ? Sides.white : Sides.black)];
            BitBoard futureMoves = this.board[directAttacker].getAllMoves(this.board, (short)directAttacker.X, (short)directAttacker.Y);
            bool isDirectCheck = futureMoves.Contains(currKingPos);
            bool isDiscoverCheck;

            this.attackingPieces[(int)AttackTypes.discovery] = ExtrapolateAttack((short)this.startCoord.X, (short)this.startCoord.Y, (short)currKingPos.X, (short)currKingPos.Y);
            this.attackingPieces[(int)AttackTypes.regular] = isDirectCheck ? endCoord : BoardSquare.Empty;

            isDiscoverCheck = this.attackingPieces[(int)AttackTypes.discovery] != BoardSquare.Empty;

            if (!isDiscoverCheck)
            {
                BoardSquare lastKingPos = this.kingPos[(int)(whiteTurn ? Sides.black : Sides.white)];

                if (moveType == ChessMove.MoveStatusCodes.queenCastle)
                {
                    isDiscoverCheck = this[lastKingPos.Y, lastKingPos.X + 1].getAllMoves(this.board, (short)(this.endCoord.X + 1), (short)this.endCoord.Y).Contains(currKingPos);
                    if (isDiscoverCheck)
                        this.attackingPieces[(int)AttackTypes.discovery] = new BoardSquare(lastKingPos.X + 1, lastKingPos.Y);
                }
                else if (moveType == ChessMove.MoveStatusCodes.queenCastle)
                {
                    isDiscoverCheck = this[lastKingPos.Y, lastKingPos.X - 1].getAllMoves(this.board, (short)(this.endCoord.X - 1), (short)this.endCoord.Y).Contains(currKingPos);
                    if (isDiscoverCheck)
                        this.attackingPieces[(int)AttackTypes.discovery] = new BoardSquare(lastKingPos.X - 1, lastKingPos.Y);
                }
                else if (moveType == ChessMove.MoveStatusCodes.enPassant)
                {
                    // Check captured square
                    this.attackingPieces[(int)AttackTypes.discovery] = ExtrapolateAttack((short)endCoord.X, (short)startCoord.Y, (short)currKingPos.X, (short)currKingPos.Y);
                    isDiscoverCheck = this.attackingPieces[(int)AttackTypes.discovery] != BoardSquare.Empty;
                }
            }

            if (isDirectCheck || isDiscoverCheck)
            {
                this.gameStatus = GameStatusCodes.check;

                // If king can't move safely, check alternatives
                if (this.board[currKingPos].getAllMoves(this.board, (short)currKingPos.X, (short)currKingPos.Y) == BitBoard.Empty)
                {
                    // Double attack, can only get out of it by moving
                    if (isDirectCheck && isDiscoverCheck)
                        this.gameStatus = GameStatusCodes.checkMate;
                    else
                    {
                        BoardSquare attackSquare = BoardSquare.Empty;

                        bool canBlockCap = false;

                        if (isDirectCheck) attackSquare = this.attackingPieces[(int)AttackTypes.regular];
                        else attackSquare = this.attackingPieces[(int)AttackTypes.discovery];

                        // Check for blocking, capture
                        foreach (BoardSquare sq in this.board)
                        {
                            Piece p = this.board[sq];

                            if (p.Colour == this.board[currKingPos].Colour)
                            {
                                BitBoard bbMoves = p.getAllMoves(this.board, (short)sq.X, (short)sq.Y);
                                foreach (BoardSquare sqMove in bbMoves)
                                {
                                    // Can block or capture
                                    if (sqMove == attackSquare || (!(board[sq] is King) && sqMove.IsBetweenPoints(currKingPos, attackSquare))
                                        || board[sq] is Pawn && ((Pawn)board[sq]).MayEnPassant(this.board, (short)sq.X, (short)sq.Y, (short)sqMove.X, (short)sqMove.Y))
                                    {
                                        canBlockCap = true;
                                        break;
                                    }
                                }

                                if (canBlockCap)
                                    break;
                            }
                        }

                        if (!canBlockCap)
                            this.gameStatus = GameStatusCodes.checkMate;
                    }
                }
            }
            else
            {
                gameStatus = GameStatusCodes.normal;

                //Check for draw conditions (stalemate, repetition, inactivity (no capture/pawn), material
                if (this.positions.isDrawByMoves())
                    this.gameStatus = GameStatusCodes.forcedDraw;
                else if (this.lastMove.IsCapture && IsDrawByMaterial())
                    this.gameStatus = GameStatusCodes.drawByMaterial;
                else
                {
                    bool isStalemate = true;
                    char nextMoveCol = whiteTurn ? Piece.NOTATION_W : Piece.NOTATION_B;

                    foreach (BoardSquare sq in this.board)
                        if (this.board[sq].Colour == nextMoveCol && this.board[sq].getAllMoves(this.board, (short)sq.X, (short)sq.Y) != BitBoard.Empty)
                        {
                            isStalemate = false;
                            break;
                        }

                    if (isStalemate)
                        this.gameStatus = GameStatusCodes.stalemate;
                }
            }
        }
示例#2
0
        /*
         * The actions that take place when a player is checkmated.
         *
         * First, the game status is upated, followed by the ratings of each player.
         */
        public void CheckMate(bool blackWon, GameStatusCodes gameStatus)
        {
            this.gameStatus = gameStatus;
            int player1Rating = PlayerWhite.Rating;
            this.blackWon = blackWon;

            if (blackWon)
            {
                PlayerWhite.CalcNewELO(PlayerBlack.Rating, 0);
                PlayerBlack.CalcNewELO(player1Rating, 1);
            }
            else
            {
                PlayerWhite.CalcNewELO(PlayerBlack.Rating, 1);
                PlayerBlack.CalcNewELO(player1Rating, 0);
            }
        }
示例#3
0
 /*
  * The actions that take place when a draw occurs
  *
  * First, the game status is upated to the code passed through as a parameter.
  * Then, the player ratings are updated accordingly.
  */
 public void Draw(GameStatusCodes reasonForDraw)
 {
     gameStatus = reasonForDraw;
     int player1Rating = PlayerWhite.Rating;
     PlayerWhite.CalcNewELO(PlayerBlack.Rating, 0.5);
     PlayerBlack.CalcNewELO(player1Rating, 0.5);
 }
示例#4
0
        /*
         * Initialize all game-driven variables who's values must be retained for the duration
         * of the game, and are not set with every move (startXCoord, for example).
         */
        public Game(Player p1, Player p2)
        {
            whiteTurn = true;
            kingPos = new BoardSquare[2] { new BoardSquare(4, 0), new BoardSquare(4, 7) };
            gameStatus = GameStatusCodes.normal;
            attackingPieces = new BoardSquare[2] {
                BoardSquare.Empty,
                BoardSquare.Empty,
            };

            allMoves = new List<ChessMove>();
            positions = new BoardPositions(Game.DRAW_LIMIT, BoardPositions.DEFAULT_START);
            PlayerWhite = p1;
            PlayerBlack = p2;

            board = new Board(this);
            board[0, 0] = new Rook(Piece.NOTATION_W);
            board[0, 1] = new Knight(Piece.NOTATION_W);
            board[0, 2] = new Bishop(Piece.NOTATION_W);
            board[0, 3] = new Queen(Piece.NOTATION_W);
            board[0, 4] = new King(Piece.NOTATION_W);
            board[0, 5] = new Bishop(Piece.NOTATION_W);
            board[0, 6] = new Knight(Piece.NOTATION_W);
            board[0, 7] = new Rook(Piece.NOTATION_W);
            board[1, 0] = new Pawn(Piece.NOTATION_W);
            board[1, 1] = new Pawn(Piece.NOTATION_W);
            board[1, 2] = new Pawn(Piece.NOTATION_W);
            board[1, 3] = new Pawn(Piece.NOTATION_W);
            board[1, 4] = new Pawn(Piece.NOTATION_W);
            board[1, 5] = new Pawn(Piece.NOTATION_W);
            board[1, 6] = new Pawn(Piece.NOTATION_W);
            board[1, 7] = new Pawn(Piece.NOTATION_W);

            board[7, 0] = new Rook(Piece.NOTATION_B);
            board[7, 1] = new Knight(Piece.NOTATION_B);
            board[7, 2] = new Bishop(Piece.NOTATION_B);
            board[7, 3] = new Queen(Piece.NOTATION_B);
            board[7, 4] = new King(Piece.NOTATION_B);
            board[7, 5] = new Bishop(Piece.NOTATION_B);
            board[7, 6] = new Knight(Piece.NOTATION_B);
            board[7, 7] = new Rook(Piece.NOTATION_B);
            board[6, 0] = new Pawn(Piece.NOTATION_B);
            board[6, 1] = new Pawn(Piece.NOTATION_B);
            board[6, 2] = new Pawn(Piece.NOTATION_B);
            board[6, 3] = new Pawn(Piece.NOTATION_B);
            board[6, 4] = new Pawn(Piece.NOTATION_B);
            board[6, 5] = new Pawn(Piece.NOTATION_B);
            board[6, 6] = new Pawn(Piece.NOTATION_B);
            board[6, 7] = new Pawn(Piece.NOTATION_B);
        }