From edba175900ecf8d46454a4ef7ae31e06058fac78 Mon Sep 17 00:00:00 2001 From: Yaakov Schlachter Date: Fri, 21 Feb 2025 14:37:42 -0500 Subject: [PATCH] Don't allow king to castle through or out of check and adjust en passant logic --- .../Runtime/Scripts/Gamerules/DefaultRules.cs | 89 +++++++++++++------ 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/Packages/com.emymin.emychess/Runtime/Scripts/Gamerules/DefaultRules.cs b/Packages/com.emymin.emychess/Runtime/Scripts/Gamerules/DefaultRules.cs index f8315d8..b5129f0 100644 --- a/Packages/com.emymin.emychess/Runtime/Scripts/Gamerules/DefaultRules.cs +++ b/Packages/com.emymin.emychess/Runtime/Scripts/Gamerules/DefaultRules.cs @@ -1,4 +1,4 @@ - + using UdonSharp; using UnityEngine; using VRC.SDKBase; @@ -77,7 +77,7 @@ private int AppendMove(int index, int x,int y,Vector2[] legalMoves) int newindex = index; if (x < 0 || x > 7 || y < 0 || y > 7) { return newindex; } if (index < legalMoves.Length) - { + { legalMoves[index] = new Vector2(x, y); if(index < legalMoves.Length - 1) { @@ -116,13 +116,13 @@ public Vector2[] GetAllPseudoLegalMovesGrid(Piece movedPiece,Piece[] grid,Piece if (!hasMoved) { if (board.GetPiece(x, y + dir* 2) == null) { - index = AppendMove(index, x, y + dir * 2, legalMoves); + index = AppendMove(index, x, y + dir * 2, legalMoves); } } } Piece pieceCaptureLeft = board.GetGridPiece(x - 1, y + dir,grid); Piece pieceCaptureRight = board.GetGridPiece(x + 1, y + dir,grid); - + if (pieceCaptureLeft != null && pieceCaptureLeft.white!=white) { index = AppendMove(index, x - 1, y + dir, legalMoves); @@ -153,12 +153,12 @@ public Vector2[] GetAllPseudoLegalMovesGrid(Piece movedPiece,Piece[] grid,Piece } else if (type == "king") { - for(int i = -1; i < 2; i++) + for (int i = -1; i < 2; i++) { - for(int j = -1; j < 2; j++) + for (int j = -1; j < 2; j++) { - Piece squarepiece = board.GetGridPiece(x + i, y + j,grid); - if(squarepiece==null||(squarepiece!=null && squarepiece.white != white)) + Piece squarepiece = board.GetGridPiece(x + i, y + j, grid); + if (squarepiece == null || (squarepiece != null && squarepiece.white != white)) { index = AppendMove(index, x + i, y + j, legalMoves); } @@ -166,27 +166,32 @@ public Vector2[] GetAllPseudoLegalMovesGrid(Piece movedPiece,Piece[] grid,Piece } if (!hasMoved) { - if (true )//|| !isKingInCheck(movedPiece.GetVec(), board.grid, board, board.PawnThatDidADoublePushLastRound, white)) //TODO very WEIRD stuff happens if I check if the king is in check here (which is necessary because castling is not allowed when the king is in check) + if (!isKingInCheck(movedPiece.GetVec(), grid, board, PawnThatDidADoublePushLastRound, white)) { - foreach(int rookColumn in rookColumns) + foreach (int rookColumn in rookColumns) { - Piece startRook = board.GetGridPiece(rookColumn, y,grid); - if (startRook!=null && startRook.type == "rook" && !startRook.hasMoved && startRook.white == white) + Piece startRook = board.GetGridPiece(rookColumn, y, grid); + if (startRook != null && startRook.type == "rook" && !startRook.hasMoved && startRook.white == white) { bool free = true; - for(int i = Mathf.Min(x, rookColumn) + 1; i < Mathf.Max(x, rookColumn); i++) + for (int i = Mathf.Min(x, rookColumn) + 1; i < Mathf.Max(x, rookColumn); i++) { - if (board.GetGridPiece(i, y,grid) != null) free = false; + if (board.GetGridPiece(i, y, grid) != null) free = false; } if (free) { int dir = Mathf.Min(x, rookColumn) == x ? 1 : -1; - index = AppendMove(index, x + dir * 2, y, legalMoves); + Vector2 throughSquare = new Vector2(x + dir, y); + Vector2 endSquare = new Vector2(x + dir * 2, y); + if (!IsSquareUnderAttack(throughSquare, white, grid, board, PawnThatDidADoublePushLastRound) && + !IsSquareUnderAttack(endSquare, white, grid, board, PawnThatDidADoublePushLastRound)) + { + index = AppendMove(index, x + dir * 2, y, legalMoves); + } } } } } - } } else if (type == "rook" || type == "bishop" || type == "queen") @@ -303,6 +308,38 @@ public bool isKingInCheck(Vector2 threatenedPos,Piece[] grid,Board board,Piece P return isKingChecked; } + /// + /// Check if a square is under attack + /// + /// + /// + /// + /// + /// + /// + private bool IsSquareUnderAttack(Vector2 square, bool white, Piece[] grid, Board board, Piece PawnThatDidADoublePush) + { + foreach (Piece opponentPiece in board.GetAllPieces()) + { + if (opponentPiece.white != white) + { + if (isCaptureFeasible(opponentPiece.GetVec(), square, opponentPiece.type)) + { + if (board.GetGridPiece(opponentPiece.x, opponentPiece.y, grid) == opponentPiece) // not captured in the test move + { + Vector2[] opponentPseudoLegalMoves = GetAllPseudoLegalMovesGrid(opponentPiece, grid, PawnThatDidADoublePush, board); + foreach (Vector2 opponentPseudoLegalMove in opponentPseudoLegalMoves) + { + if (opponentPseudoLegalMove == legalMovesEndMarker) { break; } + if (opponentPseudoLegalMove == square) { return true; } + } + } + } + } + } + return false; + } + /// /// Get all legal moves for a piece /// @@ -321,14 +358,14 @@ public Vector2[] GetAllLegalMoves(Piece movedPiece, Board board) //TODO needs so Piece[] testGrid=new Piece[currentGrid.Length]; for(int i=0;i 1)){ @@ -336,20 +373,20 @@ public Vector2[] GetAllLegalMoves(Piece movedPiece, Board board) //TODO needs so } Vector2 threatenedPos = movedPiece.type != "king" ? kingPos : pseudoLegalMove; if (isKingInCheck(threatenedPos, testGrid, board, PawnThatDidADoublePush, movedPiece.white)) { pseudoLegalMoves[i] = legalMovesIgnoreMarker; } - + } } } return pseudoLegalMoves; - + } /// /// Gets the result of moving a piece to the specified position, as well as performing capture, en passant or castling /// /// - /// Will recalculate legal moves, if you already have a list of legal moves + /// Will recalculate legal moves, if you already have a list of legal moves /// (for example during ) use to pass them /// /// @@ -373,7 +410,7 @@ public int Move(Piece movedPiece,int x,int y,Board board) Vector2[] legalMoves = GetAllLegalMoves(movedPiece, board); return MoveLegalCheck(movedPiece, x, y, board, legalMoves); } - + } /// @@ -425,7 +462,7 @@ public int MoveLegalCheck(Piece movedPiece,int x,int y, Board board,Vector2[] le } movedPiece.hasMoved = true; movedPiece._SetPosition(x, y); - + return result; } else @@ -433,7 +470,7 @@ public int MoveLegalCheck(Piece movedPiece,int x,int y, Board board,Vector2[] le movedPiece._SetPosition(movedPiece.x, movedPiece.y); return 0; } - + } /// /// Resets the board with all pieces in the correct starting positions