/// <summary> /// Calculate the actual actions available for a Chess Piece at a set of coordinates. /// </summary> /// <param name="x">The number of squares right of the bottom left square</param> /// <param name="y">The number of squares above the bottom left square</param> /// <param name="ignoreCheck">Do not check for threats to the king</param> /// <param name="attackActions">Calculate attacks</param> /// <param name="moveActions">Calculate movement</param> /// <param name="boardArray">An optional substitute board</param> /// <returns>A list of points that can be moved to</returns> public IEnumerable <Point> PieceActions(int x, int y, bool ignoreCheck = false, bool attackActions = true, bool moveActions = true, ChessPiece[,] boardArray = null) { if (boardArray == null) { boardArray = this.boardArray; } bool[,] legalActions = new bool[boardArray.GetLength(0), boardArray.GetLength(1)]; List <Point> availableActions = new List <Point>(); ChessPiece movingPeice = boardArray[x, y]; if (attackActions) { foreach (Point[] direction in movingPeice.AvailableAttacks) { foreach (Point attackPoint in direction) { Point adjustedPoint = new Point(attackPoint.x + x, attackPoint.y + y); if (ValidatePoint(adjustedPoint)) { if (boardArray[adjustedPoint.x, adjustedPoint.y] != null && boardArray[adjustedPoint.x, adjustedPoint.y].Player == movingPeice.Player) { break; } if (boardArray[adjustedPoint.x, adjustedPoint.y] != null) { AddMove(availableActions, new Point(x, y), adjustedPoint, ignoreCheck); break; } } } } } if (moveActions) { foreach (Point[] direction in movingPeice.AvailableMoves) { foreach (Point movePoint in direction) { Point adjustedPoint = new Point(movePoint.x + x, movePoint.y + y); if (ValidatePoint(adjustedPoint)) { if (boardArray[adjustedPoint.x, adjustedPoint.y] != null) { break; } AddMove(availableActions, new Point(x, y), adjustedPoint, ignoreCheck); } } } } if (movingPeice is King && ((King)movingPeice).CanCastle) { int rookX = 0; if (boardArray[rookX, y] is Rook && ((Rook)boardArray[rookX, y]).CanCastle) { bool missedCondition = false; foreach (int rangeX in Enumerable.Range(rookX + 1, Math.Abs(rookX - x) - 1)) { if (boardArray[rangeX, y] != null) { missedCondition = true; } // TODO: Validate that the king won't move through check } // TODO: Validate that king isn't currently in check missedCondition = missedCondition || KingInCheck(movingPeice.Player); if (!missedCondition) { AddMove(availableActions, new Point(x, y), new Point(x - 2, y), ignoreCheck); } } rookX = COLUMNS - 1; if (boardArray[rookX, y] is Rook && ((Rook)boardArray[rookX, y]).CanCastle) { bool missedCondition = false; foreach (int rangeX in Enumerable.Range(x + 1, Math.Abs(rookX - x) - 1)) { if (boardArray[rangeX, y] != null) { missedCondition = true; } // TODO: Validate that the king won't move through check } // TODO: Validate that king isn't currently in check missedCondition = missedCondition || KingInCheck(movingPeice.Player); if (!missedCondition) { AddMove(availableActions, new Point(x, y), new Point(x + 2, y), ignoreCheck); } } } if (movingPeice is Pawn) { Pawn pawn = (Pawn)movingPeice; int flipDirection = 1; if (pawn.Player == 1) { flipDirection = -1; } if (pawn.CanEnPassantLeft) { Point attackPoint; attackPoint = ChessPiece.GetDiagnalMovementArray(1, DiagnalDirection.FORWARD_LEFT)[0]; attackPoint.y *= flipDirection; attackPoint.y += y; attackPoint.x += x; if (ValidatePoint(attackPoint)) { AddMove(availableActions, new Point(x, y), attackPoint, ignoreCheck); } } if (pawn.CanEnPassantRight) { Point attackPoint; attackPoint = ChessPiece.GetDiagnalMovementArray(1, DiagnalDirection.FORWARD_RIGHT)[0]; attackPoint.y *= flipDirection; attackPoint.y += y; attackPoint.x += x; if (ValidatePoint(attackPoint)) { AddMove(availableActions, new Point(x, y), attackPoint, ignoreCheck); } } } return(availableActions); }