Example #1
0
 /* Take a move object and return true if the A and B
 positions are distinct from each other. */
 private bool IsMovePositionsDistinct(FormedMove move)
 {
     Tuple<int, int> posA = move.PosA;
     Tuple<int, int> posB = move.PosB;
     return !posB.Equals(posA);
 }
Example #2
0
        /* Takes a move which so far meets the requirements for a Movement type
        move on the chess board. This function checks that one of the moving piece's
        rays covers this move object (The piece itself can move in this direction/way)
        and that the way is not blocked by another piece. */
        private bool IsPieceMovementLegal(FormedMove move, ChessPosition cpm)
        {
            bool isLegalMovement = true;
            Tuple<int, int> posA = move.PosA;
            Tuple<int, int> posB = move.PosB;
            Tile tileA = cpm.Board[posA.Item1, posA.Item2];
            List<List<Tuple<int, int>>> movementRays;
            // get the rays for a piece of type=piece.Val and location=posA

            movementRays = GetPieceRay(tileA.piece.Val, posA);
            ;
            List<Tuple<int, int>> moveRayUsed = null;
            foreach (List<Tuple<int, int>> ray in movementRays)
            {
                // for pawns the rays are comprise TWO forward positions (from first move)
                // so if the pawn has already .MovedOnce don not consider the second position in the ray
                // as the pawn can no longer legally move to that position
                if ((tileA.piece.Val == EGamePieces.WhitePawn || tileA.piece.Val == EGamePieces.BlackPawn) &&
                    (tileA.piece.MovedOnce))
                {
                    ;
                    if (ray[0].Equals(posB))
                    {
                        ;
                        moveRayUsed = ray;
                        break;
                    }
                }
                // for all other cases consider the entirety of the ray
                else
                {
                    if (ray.Contains(posB))
                    {
                        moveRayUsed = ray;
                        break;
                    }
                }

            }
            if (moveRayUsed != null)
                // check there are no intermediate Pieces blocking the movement
                foreach (Tuple<int, int> tilePos in moveRayUsed)
                {
                    Tile tileAtPosition = cpm.Board[tilePos.Item1, tilePos.Item2];
                    if (!tileAtPosition.IsEmpty())
                    {
                        isLegalMovement = false;
                        break;
                    }
                    if (tilePos.Equals(posB))
                        break;
                }
            else
                isLegalMovement = false;

            return isLegalMovement;
        }
Example #3
0
 /* Takes a move object and a chess board object and returns true if
 the tile on the B position of the move is empty. */
 private bool IsMoveBEmpty(FormedMove move, ChessPosition cpm, ref Tile tileB)
 {
     tileB = cpm.Board[move.PosB.Item1, move.PosB.Item2];
     return tileB.IsEmpty();
 }
Example #4
0
        /* Takes a move object and a chess board object and returns true if
        the piece on the B position of the move belongs to the other player.

        TODO: replace with alternate call to previous functions*/
        private bool IsMoveBPieceOtherPlayer(FormedMove move, ChessPosition cpm, ref Tile tileB)
        {
            bool result = false;
            tileB = cpm.Board[move.PosB.Item1, move.PosB.Item2];
            if (!tileB.IsEmpty())
                if (!cpm.Player.Owns(tileB.piece))
                    result = true;
            return result;
        }
Example #5
0
        /* Takes a move which so far meets the requirements for an EnPassant type
        move on the chess board. This function checks that one of the moving pawn's
        diagonal rays covers this move object (The piece itself can move in this direction/way)
        and that the corresponding enpassant capture tile for this movement contains
        an enemy pawn piece to capture.*/
        private bool IsEnPassantCaptureLegal(FormedMove move, ChessPosition cpm)
        {
            bool isLegalEnPassantCapture = true;
            Tuple<int, int> posA = move.PosA;
            Tuple<int, int> posB = move.PosB;
            Tile tileA = cpm.Board[posA.Item1, posA.Item2];
            List<List<Tuple<int, int>>> epMovementRays;
            // get attack ray for the pawn on tileA
            // these are the movement rays in the case of EP
            epMovementRays = GetPieceRayPawnCapture(tileA.piece.Val, posA);
            List<Tuple<int, int>> moveRayUsed = null;
            foreach(List<Tuple<int, int>> ray in epMovementRays)
            {
                if (ray.Contains(posB))
                {
                    moveRayUsed = ray;
                    break;
                }
            }
            // so at this point:
            // have posA and posB and it is a valid enpassant-type
            // movement (diagonal to empty square)

            if (moveRayUsed != null)
            {
                // continue checking ep position
                int epX = posB.Item2;
                int epY = posA.Item1;
                Tuple<int, int> posEP = Tuple.Create(epY, epX);
                // if this computed ep square between posA and posB does not
                // match the currently valid EnPassantSq, then this is not
                // a valid EP capture
                if (!posEP.Equals(cpm.EnPassantSq))
                    isLegalEnPassantCapture = false;

            }
            else
                isLegalEnPassantCapture = false;

            return isLegalEnPassantCapture;
        }
Example #6
0
 /* Takes a move object and a chess board object and returns true if
 the piece on the A position of the move belongs to the current player. */
 private bool IsMoveAPieceCurPlayer(FormedMove move, ChessPosition cpm, ref Tile tileA)
 {
     bool result = false;
     tileA = cpm.Board[move.PosA.Item1, move.PosA.Item2];
     if (!tileA.IsEmpty())
         if (cpm.Player.Owns(tileA.piece))
             result = true;
     return result;
 }
Example #7
0
        /* Takes an input string from a view / source and returns true if it is
        in the correct chess board move format e.g. 'A5 A6'. The corresponding
        move object is also created and passed to the non-local move variable. */
        public bool ValidateInput(string input, ref FormedMove move)
        {
            // these lists contain only the valid file and ranks
            // and are indexed such that a file/rank will correspond to the col/row pos
            List<char> validFiles = "ABCDEFGH".ToList();
            List<int> validRanks = new List<int>(new int[] { 8, 7, 6, 5, 4, 3, 2, 1 });
            bool validMove = false;

            string[] chessBoardLocs = input.Split();
            Tuple<int, int> chessBoardPos1;
            Tuple<int, int> chessBoardPos2;

            if (chessBoardLocs.Length == 2)
            {
                string chessBoardLoc1 = chessBoardLocs[0];
                string chessBoardLoc2 = chessBoardLocs[1];
                {
                    char loc1File = Char.ToUpper(chessBoardLoc1[0]);
                    int loc1Rank = (int)Char.GetNumericValue(chessBoardLoc1[1]);

                    char loc2File = Char.ToUpper(chessBoardLoc2[0]);
                    int loc2Rank = (int)Char.GetNumericValue(chessBoardLoc2[1]);

                    if (validFiles.Contains(loc1File) && validRanks.Contains(loc1Rank) &&
                       (validFiles.Contains(loc2File) && validRanks.Contains(loc2Rank)))
                    {
                        int loc1Col = validFiles.IndexOf(loc1File);
                        int loc1Row = validRanks.IndexOf(loc1Rank);

                        int loc2Col = validFiles.IndexOf(loc2File);
                        int loc2Row = validRanks.IndexOf(loc2Rank);

                        chessBoardPos1 = Tuple.Create<int, int>(loc1Row, loc1Col);
                        chessBoardPos2 = Tuple.Create<int, int>(loc2Row, loc2Col);
                        move = new FormedMove(chessBoardPos1, chessBoardPos2);
                        validMove = true;
                    }
                }
            }
            return validMove;
        }
Example #8
0
        /* Apply a capture type move to the board. This capture has already been validated by
        the evaluator and found to be legal.
        There are additional actions to be made if the moving piece is a pawn and fits certain
        criteria.
        The captured piece is also added to the piecesCapd List property of this ChessPosition.*/
        private void applyCapture(FormedMove move)
        {
            Tuple<int, int> frSqPos = move.PosA;
            Tuple<int, int> toSqPos = move.PosB;

            Tile toSqTl = getTile(toSqPos);
            Tile frSqTl = getTile(frSqPos);

            Piece mvPiece = frSqTl.piece;

            // if moving piece is a pawn do additional actions //
            if (mvPiece.Val == EGamePieces.WhitePawn ||
                mvPiece.Val == EGamePieces.BlackPawn)
            {
                // if there exists a non-empty value in PromotionSelection
                // this means the capturing piece is also pawn being promoted
                if (move.PromotionSelection != EGamePieces.empty)
                    mvPiece.Val = move.PromotionSelection;
                // in the cases where a pawns first move is a capture, need to
                // set this to prevent the 2 move option only applying to first 'movement'
                mvPiece.MovedOnce = true;
            }

            // add the captured to the list
            addToCaptured(toSqTl.piece.Val);

            // move the piece
            updatePosWithPiece(toSqPos, mvPiece);
            updatePosWithPiece(frSqPos, null);
        }
Example #9
0
 /* The Entry point for a move application, this method selects the
 appropriate type of move to make based on the moveType property. */
 public void applyMove(FormedMove move)
 {
     switch (move.MoveType)
     {
         case EChessMoveTypes.Castle:
             applyCastle(move);
             break;
         case EChessMoveTypes.Capture:
             applyCapture(move);
             break;
         case EChessMoveTypes.Movement:
             applyMovement(move);
             break;
         case EChessMoveTypes.EpMovement:
             applyEnPassantCapture(move);
             break;
         default:
             throw new ArgumentException($"Unexpected value: {move.MoveType}, for moveType");
     }
 }
Example #10
0
        /* Take a valid-format move object and check if it may be legally
        applied to the current chess game. It must pass the following checks:
        -the locations are distinct and
        -the A tile contains a piece of the current player
        Also one of the following:
            -the B tile contains a piece of the current player (further castle checks) or
            -the B tile contains a piece of the opponent player (further capture checks) or
            -the B tile is empty:
                -(further en passant checks)
                -(further movement checks)
        Finally it must check, if the move were to be applied, that it does not leave the
        current player's king in check.*/
        public bool IsValidMove(ref FormedMove move, ChessPositionModel cpm, ref List<Tuple<int, int>> kingCheckedBy)
        {
            bool validMove = false;
            Tile tileA = new Tile();
            Tile tileB = new Tile();

            if (IsMovePositionsDistinct(move))
            {
                if (IsMoveAPieceCurPlayer(move, cpm, ref tileA))
                {
                    // check if its a castling
                    if (IsMoveBPieceCurPlayer(move, cpm, ref tileB))
                    {
                        validMove = false; // IsLegalCastle? - this involves calls to isKingInCheck
                        move.MoveType = EChessMoveTypes.Castle;
                    }
                    // check if its a capture
                    else if (IsMoveBPieceOtherPlayer(move, cpm, ref tileB))
                    {
                        validMove = IsCaptureLegal(move, cpm);
                        move.MoveType = EChessMoveTypes.Capture;
                    }
                    // check if its a movement
                    else if (IsMoveBEmpty(move, cpm, ref tileB))
                    {
                        if (validMove = IsPieceMovementLegal(move, cpm))
                        {
                            move.MoveType = EChessMoveTypes.Movement;
                        }
                        else if (validMove = IsEnPassantCaptureLegal(move, cpm))
                        {
                            move.MoveType = EChessMoveTypes.EpMovement;
                        }
                    }
                }
            }
            // if its a valid move so far, check if there is a pawn promotion,
            // then apply the move to a copy of the chess position and
            // finally check it passes a check test
            if (validMove)
            {
                // if there is a pawn promotion the player is prompted for the promotion piece and it is added to the move object
                MoveIncludesPawnPromotion(ref move, cpm);

                // a copy of the chess position is made so that the move may
                // be applied in order for the king-check to be checked without
                // causing the chess position to update the display
                ChessPosition cpCopy = cpm.getChessPositionCopy();
                cpCopy.applyMove(move);
                // after this application of the move
                if (IsKingInCheck(cpCopy, ref kingCheckedBy))
                    validMove = false;
            }
            return validMove;
        }
Example #11
0
        /* Apply a movement type move to the board. This move has already been validated by
        the evaluator and found to be legal.
        There are additional actions to be made if the moving piece is a pawn and fits certain
        criteria. */
        private void applyMovement(FormedMove move)
        {
            Tuple<int, int> frSqPos = move.PosA;
            Tuple<int, int> toSqPos = move.PosB;

            Tile frSqTl = getTile(frSqPos);
            Tile toSqTl = getTile(toSqPos);

            Piece mvPiece = frSqTl.piece;

            // if moving piece is a pawn do additional actions //
            if (mvPiece.Val == EGamePieces.WhitePawn ||
                mvPiece.Val == EGamePieces.BlackPawn)
            {
                // if it has moved two squares on its first move it can be captured En Passant
                if (!mvPiece.MovedOnce && mvTwoTiles(frSqPos, toSqPos))
                    this.EnPassantSq = toSqPos;

                // if there exists a non-empty value in PromotionSelection
                // this means the moving piece is a pawn being promoted
                if (move.PromotionSelection != EGamePieces.empty)
                    mvPiece.Val = move.PromotionSelection;

                mvPiece.MovedOnce = true;
            }

            // move the piece
            updatePosWithPiece(toSqPos, mvPiece);
            updatePosWithPiece(frSqPos, null);
        }
Example #12
0
        /* Apply an En Passant type move to the board. This move has already been validated by
        the evaluator and found to be legal and there exists an opponent piece on the EnPassant
        Square which can be captured.
        As in a normal capture, the piece captured En Passant is also added to the piecesCapd
        List property of this ChessPosition.*/
        private void applyEnPassantCapture(FormedMove move)
        {
            Tuple<int, int> frSqPos = move.PosA;
            Tuple<int, int> toSqPos = move.PosB;

            // Compute En Passant Square
            int epSqRank = frSqPos.Item1;
            int epSqFile = toSqPos.Item2;
            Tuple<int, int> epSqPos = Tuple.Create(epSqRank, epSqFile);

            Tile frSqTl = getTile(frSqPos);
            Tile toSqTl = getTile(toSqPos);
            Tile epSqTl = getTile(epSqPos);

            Piece mvPiece = frSqTl.piece;

            // move the pawn
            updatePosWithPiece(toSqPos, mvPiece);
            updatePosWithPiece(frSqPos, null);

            // add the captured to the list
            addToCaptured(epSqTl.piece.Val);
            updatePosWithPiece(epSqPos, null);
        }
Example #13
0
 /* Apply a Castle type move to the board. This move has already been validated by
 the evaluator and found to be legal. */
 private void applyCastle(FormedMove move)
 {
 }
Example #14
0
 /* This function receives a move object and the chess game and checks if the move also
 includes a pawn promotion, if it does it prompts the player for the selection piece, and
 adds it to the FormedMove. If it does not it ends silently
 TODO: could change it back to return bool, ref the selection piece then add it to move in the calling code ~~style issue*/
 private void MoveIncludesPawnPromotion(ref FormedMove move, ChessPosition cpm)
 {
     Piece mvPiece = cpm.Board[move.PosA.Item1, move.PosA.Item2].piece;
     Tuple<int, int> posB = move.PosB;
     // if moving piece is a pawn and posB isHighRank
     if ((mvPiece.Val == EGamePieces.WhitePawn || mvPiece.Val == EGamePieces.BlackPawn) &&
         (IsHighRank(posB)))
     {
         // Safe invoke for popup onto main thread via viewRef
         PromotionSelectionPopup(ref move, mvPiece);
     }
 }
Example #15
0
        /* Takes a move which so far meets the requirements for a Capture type
        move on the chess board. This function checks that the one of the capturer
        piece's rays covers this move object (The piece itself can move in this way)
        and that the way is not blocked by another piece en route.

        Note: This is very similar to the IsPieceMovementLegal function, only
        difference is that the check for pieces on a tile is moved after the
        check for the final tile (since the final tile will have a piece on it:
        the piece being captured, and dont want the code to consider that as an
        intermediate piece which would block the capture.

        Other difference is that if the capturer piece is of type pawn, a unique
        set of pawn capture rays are gotten (Pawn only piece to use different rays
        for capture and movement). */
        private bool IsCaptureLegal(FormedMove move, ChessPosition cpm)
        {
            bool isLegalCapture = true;

            Tuple<int, int> posA = move.PosA;
            Tuple<int, int> posB = move.PosB;

            Tile tileA = cpm.Board[posA.Item1, posA.Item2];
            List<List<Tuple<int, int>>> captureRays;

            if (tileA.piece.Val == EGamePieces.BlackPawn || tileA.piece.Val == EGamePieces.WhitePawn)
                captureRays = GetPieceRayPawnCapture(tileA.piece.Val, posA);
            else
                captureRays = GetPieceRay(tileA.piece.Val, posA);

            List<Tuple<int, int>> captureRayUsed = null;
            foreach (List<Tuple<int, int>> ray in captureRays)
            {
                if (ray.Contains(posB))
                {
                    captureRayUsed = ray;
                    break;
                }
            }
            if (captureRayUsed != null)
                // check there are no intermediate Pieces blocking the capture movement
                foreach (Tuple<int, int> position in captureRayUsed)
                {
                    if (position.Equals(posB))
                        break;
                    Tile tileAtPosition = cpm.Board[position.Item1, position.Item2];
                    if (!tileAtPosition.IsEmpty())
                    {
                        isLegalCapture = false;
                        break;
                    }
                }
            else
                isLegalCapture = false;

            return isLegalCapture;
        }
Example #16
0
 /* Make a thread safe invoke on the viewRef in order to use it as the parent argument
 to showDialog for the promotion selection form. This is called by Move includes pawn promotion. */
 private void PromotionSelectionPopup(ref FormedMove move, Piece mvPiece)
 {
     if (this.viewRef.InvokeRequired)
     {
         PromotionSelectionPopupCallback d = new PromotionSelectionPopupCallback(PromotionSelectionPopup);
         this.viewRef.Invoke(d, new object[] { move, mvPiece });
     }
     else
     {
         EGamePieces promotionPiece;
         EGamePieces promotionPieceDefault;
         View.PromotionSelection promotionSelection = new View.PromotionSelection(mvPiece);
         promotionPieceDefault = promotionSelection.DefaultPiece; // (queen)
         // remove the ability to x close the dialog before a piece is selected
         promotionSelection.ControlBox = false;
         if (promotionSelection.ShowDialog(this.viewRef) == System.Windows.Forms.DialogResult.OK)
         {
             promotionPiece = promotionSelection.SelectedPiece;
             promotionSelection.Dispose();
             move.PromotionSelection = promotionPiece;
         }
         else
             move.PromotionSelection = promotionPieceDefault;
     }
 }
Example #17
0
        /* This is the Game Loop for a Tic Tac Toe Game. This is run while a
        game is in progress in a seperate thread. When the game meets an ending criteria
        (winner) this thread will end naturally. This thread may also be
        terminated externally. */
        private void TicTacToeGameLoop()
        {
            FormedMove move;
            string winner = null; // change to player
            bool isMaxTurns = false;

            while (true)
            {
                // check if a winner has been found or reached max turns
                if (tictactoeModel.IsWinningPosition(ref winner) || tictactoeModel.IsMaxTurns(ref isMaxTurns))
                    break;

                this.Message = $"Player {tictactoeModel.Player.PlayerValue}, make your move";
                move = null;
                // check if display has provided a move
                if (gameInput != null)
                {
                    move = new FormedMove(gameInput);
                    if (tictactoeModel.IsValidMove(move))
                    {
                        tictactoeModel.applyMove(move);
                        tictactoeModel.ChangePlayer();
                    }
                    else
                        this.Message = "The move was not valid";
                    gameInput = null;
                }
            }
            // at this point game has ended
            if (winner != null)
                this.Message = $"Player {winner} has won the game!";
            else if (isMaxTurns)
                this.Message = "Draw, no more moves can be made";
        }