From e1980eb25f9fdd015837145acf72b3a820cae6b3 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 12 Aug 2023 18:27:32 +0200 Subject: [PATCH] Add HasCastled in BoardAPI --- Chess-Challenge/src/API/Board.cs | 6 ++++++ Chess-Challenge/src/Framework/Chess/Board/Board.cs | 11 +++++++---- .../src/Framework/Chess/Board/GameState.cs | 6 +++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Chess-Challenge/src/API/Board.cs b/Chess-Challenge/src/API/Board.cs index 2b284d71f..45ee3211e 100644 --- a/Chess-Challenge/src/API/Board.cs +++ b/Chess-Challenge/src/API/Board.cs @@ -159,6 +159,12 @@ public bool IsDraw() bool IsRepetition() => repetitionHistory.Contains(board.ZobristKey); } + /// + /// Does the given player has castled? + /// (this will only detect castled made during the game moves) + /// + public bool HasCastled(bool white) => white ? board.currentGameState.hasWhiteCastled : board.currentGameState.hasBlackCastled; + /// /// Does the given player still have the right to castle kingside? /// Note that having the right to castle doesn't necessarily mean castling is legal right now diff --git a/Chess-Challenge/src/Framework/Chess/Board/Board.cs b/Chess-Challenge/src/Framework/Chess/Board/Board.cs index fa683f743..7d0202e4c 100644 --- a/Chess-Challenge/src/Framework/Chess/Board/Board.cs +++ b/Chess-Challenge/src/Framework/Chess/Board/Board.cs @@ -139,6 +139,9 @@ public void MakeMove(Move move, bool inSearch = true) int newCastlingRights = currentGameState.castlingRights; int newEnPassantFile = 0; + bool hasWhiteCastled = currentGameState.hasWhiteCastled || IsWhiteToMove && move.MoveFlag == Move.CastleFlag; + bool hasBlackCastled = currentGameState.hasBlackCastled || !IsWhiteToMove && move.MoveFlag == Move.CastleFlag; + // Update bitboard of moved piece (pawn promotion is a special case and is corrected later) MovePiece(movedPiece, startSquare, targetSquare); @@ -272,7 +275,7 @@ public void MakeMove(Move move, bool inSearch = true) newFiftyMoveCounter = 0; } - GameState newState = new(capturedPieceType, newEnPassantFile, newCastlingRights, newFiftyMoveCounter, newZobristKey); + GameState newState = new(capturedPieceType, newEnPassantFile, newCastlingRights, hasWhiteCastled, hasBlackCastled, newFiftyMoveCounter, newZobristKey); gameStateHistory.Push(newState); currentGameState = newState; hasCachedInCheckValue = false; @@ -395,7 +398,7 @@ public void MakeNullMove() newZobristKey ^= Zobrist.sideToMove; newZobristKey ^= Zobrist.enPassantFile[currentGameState.enPassantFile]; - GameState newState = new(PieceHelper.None, 0, currentGameState.castlingRights, currentGameState.fiftyMoveCounter + 1, newZobristKey); + GameState newState = new (PieceHelper.None, 0, currentGameState.castlingRights, currentGameState.hasWhiteCastled, currentGameState.hasBlackCastled, currentGameState.fiftyMoveCounter + 1, newZobristKey); currentGameState = newState; gameStateHistory.Push(currentGameState); UpdateSliderBitboards(); @@ -510,9 +513,9 @@ public void LoadPosition(string fen) plyCount = (posInfo.moveCount - 1) * 2 + (IsWhiteToMove ? 0 : 1); // Set game state (note: calculating zobrist key relies on current game state) - currentGameState = new GameState(PieceHelper.None, posInfo.epFile, castlingRights, posInfo.fiftyMovePlyCount, 0); + currentGameState = new GameState(PieceHelper.None, posInfo.epFile, castlingRights, false, false, posInfo.fiftyMovePlyCount, 0); ulong zobristKey = Zobrist.CalculateZobristKey(this); - currentGameState = new GameState(PieceHelper.None, posInfo.epFile, castlingRights, posInfo.fiftyMovePlyCount, zobristKey); + currentGameState = new GameState(PieceHelper.None, posInfo.epFile, castlingRights, false, false, posInfo.fiftyMovePlyCount, zobristKey); RepetitionPositionHistory.Push(zobristKey); diff --git a/Chess-Challenge/src/Framework/Chess/Board/GameState.cs b/Chess-Challenge/src/Framework/Chess/Board/GameState.cs index 23619d471..8e86bd5f2 100644 --- a/Chess-Challenge/src/Framework/Chess/Board/GameState.cs +++ b/Chess-Challenge/src/Framework/Chess/Board/GameState.cs @@ -5,6 +5,8 @@ public readonly struct GameState public readonly int capturedPieceType; public readonly int enPassantFile; public readonly int castlingRights; + public readonly bool hasWhiteCastled; + public readonly bool hasBlackCastled; public readonly int fiftyMoveCounter; public readonly ulong zobristKey; @@ -13,11 +15,13 @@ public readonly struct GameState public const int ClearBlackKingsideMask = 0b1011; public const int ClearBlackQueensideMask = 0b0111; - public GameState(int capturedPieceType, int enPassantFile, int castlingRights, int fiftyMoveCounter, ulong zobristKey) + public GameState(int capturedPieceType, int enPassantFile, int castlingRights, bool hasWhiteCastled, bool hasBlackCastled, int fiftyMoveCounter, ulong zobristKey) { this.capturedPieceType = capturedPieceType; this.enPassantFile = enPassantFile; this.castlingRights = castlingRights; + this.hasWhiteCastled = hasWhiteCastled; + this.hasBlackCastled = hasBlackCastled; this.fiftyMoveCounter = fiftyMoveCounter; this.zobristKey = zobristKey; }