/* Used when a new chess position is created. The property copies are made and then this constructor is called with the copies. */ public ChessPosition(int size, Tile[,] board, Player player, Dictionary<char, bool> castle, Tuple<int, int> enPassantSq, int halfmoveClock, List<EGamePieces> piecesCapd) { this.Size = size; this.Board = board; this.Player = player; this.Castle = castle; this.EnPassantSq = enPassantSq; this.HalfMoveClock = halfmoveClock; this.PiecesCapd = piecesCapd; }
/* 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; }
/* 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(); }
/* 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; }
/* 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; }
/* Returns a ChessPosition object which is a deep copy of this one. Since this method is also inherited by the ChessPositionModel, if the CPM produces this object it will be a deep copy of the ChessPositionModel object as if it were a ChessPosition. (CPM minus handlers etc). This function will be used during evaluation in the king check phase, and will also be used during the move search of the ai function. */ public ChessPosition getChessPositionCopy() { int dimCopy = Size; // deep copy the board manually // Tile[,] boardCopy = new Tile[dimCopy, dimCopy]; for (int j = 0; j < dimCopy; j ++) { for (int k = 0; k < dimCopy; k ++) { Tile tileCopy = new Tile(); if (!Board[j,k].IsEmpty()) { Piece piece = Board[j, k].piece; EGamePieces val = piece.Val; bool mv = piece.MovedOnce; Piece pieceCopy = new Piece(val); pieceCopy.MovedOnce = mv; tileCopy.piece = pieceCopy; } boardCopy[j, k] = tileCopy; } } // copy rest of ChessPosition properties Player playerCopy = new Player(this.Player.PlayerValue); Dictionary<char, bool> castleCopy = new Dictionary<char, bool>(Castle); Tuple<int, int> enPassantSqCopy = (EnPassantSq == null) ? null : Tuple.Create(EnPassantSq.Item1, EnPassantSq.Item2); int halfmoveClockCopy = HalfMoveClock; List<EGamePieces> piecesCapdCopy = new List<EGamePieces>(PiecesCapd); // create and return the copy ChessPosition cpCopy = new ChessPosition(dimCopy, boardCopy, playerCopy, castleCopy, enPassantSqCopy, halfmoveClockCopy, piecesCapdCopy); return cpCopy; }