/// <summary> /// Finds out what row the coordinates are in with a reversed perspective /// </summary> /// <param name="coords"></param> /// <param name="reversed"></param> /// <returns></returns> public static int Column(this Coords coords, bool reversed) { if (reversed) { return(7 - coords.Column()); } return(coords.Column()); }
/// <summary> /// Reusable method for calculating valid position within the board /// </summary> /// <param name="board"></param> /// <param name="corner"></param> /// <param name="op"></param> /// <param name="xRay"></param> /// <param name="updateBlockingPieces"></param> /// <returns></returns> private List <Coords> HandleCoords(Tile[] board, int corner, Func <int, int, int> op, bool xRay, bool updateBlockingPieces) { List <Coords> coordsList = new List <Coords>(); bool finished = false; int rotation = 1; while (!finished) { Coords coordinate = (Coords)op((int)Coords, rotation); if (!ValidCoordinate(board, coordinate, corner, true)) { break; } if (board[(int)coordinate].Piece?.Side == Side) { if (!xRay) { break; } finished = true; } if (board.HasPawnOnTile(coordinate) && board[(int)coordinate].Piece.Side != Side) { if (updateBlockingPieces) { if (coordinate.Column() != corner) { HandleBlocking(board, board[(int)coordinate].Piece, op, corner, rotation + 1); } HandleTargetKing(board, op, corner, rotation); } finished = true; } coordsList.Add(coordinate); if (coordinate.Column() == corner) { finished = true; } rotation++; } return(FilterKingProtectionCoords(coordsList)); }
/// <summary> /// Finds out if coordinate tile is white /// </summary> /// <param name="coords"></param> /// <returns></returns> public static bool IsWhiteTile(this Coords coords) { bool reverseTile = coords.Row() % 2 != 0; bool whiteTile = coords.Column() % 2 == 0; return(reverseTile ? !whiteTile : whiteTile); }
/// <summary> /// Unique move for castling /// </summary> /// <param name="fromCoords"></param> /// <param name="newCoords"></param> /// <returns>returns false if castling was not activated</returns> private bool MoveCastling(Coords fromCoords, Coords newCoords) { Tile kingTile = Board.Tiles[(int) fromCoords]; if (kingTile.Piece.EPiece != EPiece.King || ((King)kingTile.Piece).HasMoved) return false; int fixRookCoords = newCoords.Column() == 5 ? 2 : -1; Tile rookTile = Board.Tiles[(int) newCoords + fixRookCoords]; if (kingTile.Piece?.EPiece != EPiece.King || rookTile.Piece?.EPiece != EPiece.Rook || kingTile.Piece?.Side != rookTile.Piece?.Side) return false; if (rookTile.Coords.Column() == 7) { //Rook Board.Tiles[(int) rookTile.Coords - 3].Piece = rookTile.Piece; rookTile.Piece.Move(rookTile.Coords - 3); //King Board.Tiles[(int) kingTile.Coords + 2].Piece = kingTile.Piece; kingTile.Piece.Move(kingTile.Coords + 2); //Update Board.Tiles[(int) fromCoords].Piece = null; Board.Tiles[(int) newCoords + fixRookCoords].Piece = null; OnPieceMoved(rookTile.Piece, rookTile.Coords, rookTile.Coords - 3); OnPieceMoved(kingTile.Piece, kingTile.Coords, kingTile.Coords + 2); } else { //Rook Board.Tiles[(int) rookTile.Coords + 2].Piece = rookTile.Piece; rookTile.Piece.Move(rookTile.Coords + 2); OnPieceMoved(rookTile.Piece, rookTile.Coords, rookTile.Coords + 2); //King Board.Tiles[(int) kingTile.Coords - 2].Piece = kingTile.Piece; kingTile.Piece.Move(kingTile.Coords - 2); OnPieceMoved(kingTile.Piece, kingTile.Coords, kingTile.Coords - 2); //Update Board.Tiles[(int) fromCoords].Piece = null; Board.Tiles[(int) newCoords + fixRookCoords].Piece = null; OnPieceMoved(rookTile.Piece, rookTile.Coords, rookTile.Coords + 2); OnPieceMoved(kingTile.Piece, kingTile.Coords, kingTile.Coords - 2); } UpdateGameCycle(); return true; }
/// <summary> /// General Check if a given coordinate is valid /// </summary> /// <param name="board"></param> /// <param name="coords"></param> /// <param name="sideCorner"></param> /// <param name="ignoreOwnPiece">Ignores the check that you can't take over your own pieces</param> /// <returns></returns> protected bool ValidCoordinate(Tile[] board, Coords coords, int sideCorner, bool ignoreOwnPiece = false) { if (!coords.IsInsideBoard()) { return(false); } if (sideCorner != -1 && Coords.Column() == sideCorner) { return(false); } if (!ignoreOwnPiece && board.HasPawnOnTile(coords) && board[(int)coords].Piece.Side == Side && board[(int)coords].Piece != this) { return(false); } return(true); }
/// <summary> /// Calculates the attack line of sight to the target /// Ghost targets are still able to attack when moved but can't be blocked by other pieces /// Attack line includes attacking pieces coords /// </summary> /// <param name="board"></param> /// <param name="op"></param> /// <param name="rotation"></param> /// <param name="corner"></param> /// <returns></returns> private List <AttackCoord> GetAttackLine(Tile[] board, Func <int, int, int> op, int rotation, int corner) { List <AttackCoord> attackList = new List <AttackCoord>(); bool finished = false; bool outOfBounds = false; bool isAttackBlockable = false; while (!finished) { Coords coordinate = (Coords)op((int)Coords, rotation); if (!ValidCoordinate(board, coordinate, corner) || coordinate.Column() == corner) { outOfBounds = true; rotation--; continue; } if (board.HasPawnOnTile(coordinate)) { if (outOfBounds && board[(int)coordinate].Piece.EPiece == EPiece.King) { isAttackBlockable = true; } if (board[(int)coordinate].Piece == this) { finished = true; } } attackList.Add(new AttackCoord(coordinate, isAttackBlockable)); rotation = outOfBounds ? rotation - 1 : rotation + 1; } return(attackList.Distinct().ToList()); }