Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3b4a22f
First pass TTs (~55 elo)
TomaszJaworski777 Sep 6, 2023
6033f24
Merge branch 'main' into transposition-tables
TomaszJaworski777 Sep 6, 2023
224f247
Additional TT tests
TomaszJaworski777 Sep 6, 2023
e58d0c4
Merge branch 'main' into transposition-tables
TomaszJaworski777 Sep 6, 2023
d4a7b4b
Merge branch 'main' into transposition-tables
TomaszJaworski777 Sep 7, 2023
2f655a0
Added comments to TTs
TomaszJaworski777 Sep 7, 2023
d15a647
Fixed empty go command
TomaszJaworski777 Sep 7, 2023
06650b5
Merge branch 'main' into transposition-tables
TomaszJaworski777 Sep 7, 2023
d310bdb
Implemented node type in search and qsearch
gab8192 Sep 7, 2023
dbc52cd
Cleanups and comments
TomaszJaworski777 Sep 8, 2023
24427cb
Improve comments and fix nodes measurement
gab8192 Sep 8, 2023
70a0b97
BitboardShort
TomaszJaworski777 Sep 8, 2023
99581b0
Merge branch 'transposition-tables' of https://github.com/TomaszJawor…
TomaszJaworski777 Sep 8, 2023
1e02550
Get rid of BitboardInt, make normal fields for Board flags
gab8192 Sep 8, 2023
5665df2
Only calculate whether side to move is in check
gab8192 Sep 8, 2023
1596ed8
Fix compilation for debug mode
gab8192 Sep 8, 2023
5792d44
Added AggresiveOptimization attribute to a fewfunctions
gab8192 Sep 8, 2023
ff0daaa
Clean up IsSquareAttacked
gab8192 Sep 8, 2023
e430f0d
Update EngineCredentials.cs
TomaszJaworski777 Sep 8, 2023
8b8068e
Fixed MoveData.
gab8192 Sep 8, 2023
8027c8d
Adjustments
TomaszJaworski777 Sep 8, 2023
29e9feb
Merge branch 'transposition-tables' of https://github.com/TomaszJawor…
TomaszJaworski777 Sep 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Benchmarks/Structures/BoardBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public BoardData IsKingInCheck()
BoardData board = new();
for (int i = 0; i < 100; i++)
{
Helpers.Use(board.IsBlackKingInCheck);
Helpers.Use(board.IsSideToMoveInCheck);
}

return board;
Expand All @@ -38,7 +38,7 @@ public BoardData SetIsKingInCheck()
BoardData board = new();
for (int i = 0; i < 100; i++)
{
board.IsBlackKingInCheck = 0;
board.IsSideToMoveInCheck = false;
}

return board;
Expand All @@ -50,7 +50,7 @@ public BoardData SetCanWhiteCastleQueenSide()
BoardData board = new();
for (int i = 0; i < 100; i++)
{
board.CanWhiteCastleQueenSide = 0;
board.CanWhiteCastleQueenSide = false;
}

return board;
Expand Down
102 changes: 35 additions & 67 deletions Engine/Board/BoardData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,85 +9,47 @@ public partial struct BoardData
{
private PieceBoard _pieces; //piece bitboards ot represent board state (https://www.chessprogramming.org/Bitboards). I used denser board solution to reduce size and sped up copy process (https://www.chessprogramming.org/Bitboard_Board-Definition#Denser_Board)
private PieceLookup _pieceLookup; //mailbox tyle 8x8 array of pieces for easy lookup (https://www.chessprogramming.org/Mailbox)
private BitboardInt _miscData; // {castle - 4} {side to move - 1} {white king in check - 1} {black king in check - 1} {moves - 10} {half moves - 7} {en passant - 6} = 30 bit


#region Proporties
public int EnPassantSquareIndex
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetValueChunk( 0, 63 );
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set => _miscData.SetValueChunk( 0, 63, value );
get; set;
}
public int HalfMoves
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetValueChunk( 6, 127 );
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set => _miscData.SetValueChunk( 6, 127, value );
get; set;
}
public int Moves
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetValueChunk( 13, 1023 );
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set => _miscData.SetValueChunk( 13, 1023, value );
}
public int IsBlackKingInCheck
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetBitValue( 23 ) >> 23;
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set { if (value > 0) _miscData.SetBitToOne( 23 ); else _miscData.SetBitToZero( 23 ); }
get; set;
}
public int IsWhiteKingInCheck
public bool IsSideToMoveInCheck
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetBitValue( 24 ) >> 24;
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set { if (value > 0) _miscData.SetBitToOne( 24 ); else _miscData.SetBitToZero( 24 ); }
get; set;
}
public int SideToMove
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetBitValue( 25 ) >> 25;
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set { if (value > 0) _miscData.SetBitToOne( 25 ); else _miscData.SetBitToZero( 25 ); }
get; set;
}
public int CanWhiteCastleQueenSide
public bool CanWhiteCastleQueenSide
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetBitValue( 26 ) >> 26;
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set { if (value > 0) _miscData.SetBitToOne( 26 ); else _miscData.SetBitToZero( 26 ); }
get; set;
}
public int CanWhiteCastleKingSide
public bool CanWhiteCastleKingSide
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetBitValue( 27 ) >> 27;
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set { if (value > 0) _miscData.SetBitToOne( 27 ); else _miscData.SetBitToZero( 27 ); }
get; set;
}
public int CanBlackCastleQueenSide
public bool CanBlackCastleQueenSide
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetBitValue( 28 ) >> 28;
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set { if (value > 0) _miscData.SetBitToOne( 28 ); else _miscData.SetBitToZero( 28 ); }
get; set;
}
public int CanBlackCastleKingSide
public bool CanBlackCastleKingSide
{
[MethodImpl( MethodImplOptions.AggressiveInlining )]
get => _miscData.GetBitValue( 29 ) >> 29;
[MethodImpl( MethodImplOptions.AggressiveInlining )]
set { if (value > 0) _miscData.SetBitToOne( 29 ); else _miscData.SetBitToZero( 29 ); }
get; set;
}
public ulong ZobristKey
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set;
get; set;
}

#endregion
Expand All @@ -96,20 +58,26 @@ public BoardData()
{
_pieces = default;
_pieceLookup = default;
_miscData = default;
ZobristKey = 0;

foreach (ref PieceType piece in _pieceLookup)
piece = PieceType.None;
}

#region Basic Methods

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Bitboard GetAllPieces() => _pieces[6] | _pieces[7];

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public Bitboard GetPiecesBitboardForSide( int side ) => _pieces[6 + side];

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public Bitboard GetPieceBitboard( int pieceIndex ) => _pieces[pieceIndex];

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Bitboard GetPieceBitboard(PieceType pieceType) => _pieces[(int) pieceType];

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public Bitboard GetPieceBitboard( PieceType pieceType, int side ) => GetPieceBitboard( (int)pieceType, side );

Expand All @@ -128,27 +96,27 @@ public PieceType GetPieceOnSquare( int squareIndex, int side )
}

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void SetPieceOnSquare( PieceType pieceType, int side, int sqaureIndex ) => SetPieceOnSquare( (int)pieceType, side, sqaureIndex );
public void SetPieceOnSquare( PieceType pieceType, int side, int squareIndex ) => SetPieceOnSquare( (int)pieceType, side, squareIndex );

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void SetPieceOnSquare( int pieceIndex, int side, int sqaureIndex )
public void SetPieceOnSquare( int pieceIndex, int side, int squareIndex )
{
_pieces[pieceIndex].SetBitToOne( sqaureIndex );
_pieces[6 + side].SetBitToOne( sqaureIndex );
_pieceLookup[sqaureIndex] = (PieceType)pieceIndex;
ZobristKey ^= ZobristHashing.GetSeed( pieceIndex, side, sqaureIndex );
_pieces[pieceIndex].SetBitToOne( squareIndex );
_pieces[6 + side].SetBitToOne( squareIndex );
_pieceLookup[squareIndex] = (PieceType)pieceIndex;
ZobristKey ^= ZobristHashing.GetSeed( pieceIndex, side, squareIndex );
}

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void RemovePieceOnSquare( PieceType pieceType, int side, int sqaureIndex ) => RemovePieceOnSquare( (int)pieceType, side, sqaureIndex );
public void RemovePieceOnSquare( PieceType pieceType, int side, int squareIndex ) => RemovePieceOnSquare( (int)pieceType, side, squareIndex );

[MethodImpl( MethodImplOptions.AggressiveInlining )]
public void RemovePieceOnSquare( int pieceIndex, int side, int sqaureIndex )
public void RemovePieceOnSquare( int pieceIndex, int side, int squareIndex )
{
_pieces[pieceIndex].SetBitToZero( sqaureIndex );
_pieces[6 + side].SetBitToZero( sqaureIndex );
_pieceLookup[sqaureIndex] = PieceType.None;
ZobristKey ^= ZobristHashing.GetSeed( pieceIndex, side, sqaureIndex );
_pieces[pieceIndex].SetBitToZero( squareIndex );
_pieces[6 + side].SetBitToZero( squareIndex );
_pieceLookup[squareIndex] = PieceType.None;
ZobristKey ^= ZobristHashing.GetSeed( pieceIndex, side, squareIndex );
}
#endregion
}
Expand Down
11 changes: 5 additions & 6 deletions Engine/Board/BoardDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,15 @@ public void Draw()
Console.ForegroundColor = ConsoleColor.Gray;

Console.WriteLine( SideToMove == 0 ? "White to move" : "Black to move" );
var whiteQueenCastle = CanWhiteCastleQueenSide > 0 ? 'Q' : '-';
var whiteKingCastle = CanWhiteCastleKingSide > 0 ? 'K' : '-';
var blackQueenCastle = CanBlackCastleQueenSide > 0 ? 'q' : '-';
var blackKingCastle = CanBlackCastleKingSide > 0 ? 'k' : '-';
var whiteQueenCastle = CanWhiteCastleQueenSide ? 'Q' : '-';
var whiteKingCastle = CanWhiteCastleKingSide ? 'K' : '-';
var blackQueenCastle = CanBlackCastleQueenSide ? 'q' : '-';
var blackKingCastle = CanBlackCastleKingSide ? 'k' : '-';
Console.WriteLine( $"Castle Rights: {whiteKingCastle}{whiteQueenCastle}{blackKingCastle}{blackQueenCastle}" );
Console.WriteLine( $"Half moves: {HalfMoves}, Moves: {Moves}" );
var enPassantSquareText = EnPassantSquareIndex is 0 ? "-" : SquareHelpers.SquareIndexToString(EnPassantSquareIndex);
Console.WriteLine( $"En Passant: {enPassantSquareText}" );
Console.WriteLine( $"White king in check: {IsWhiteKingInCheck > 0}" );
Console.WriteLine( $"Black king in check: {IsBlackKingInCheck > 0}" );
Console.WriteLine( $"Stm in check: {IsStmInCheck}" );
Console.WriteLine( $"Hash: {ZobristKey}" );
Console.WriteLine( $"Is repeated: {MoveHistory.IsRepetition( ZobristKey )}" );
Console.WriteLine();
Expand Down
13 changes: 6 additions & 7 deletions Engine/Board/BoardProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public static BoardData Create( ReadOnlySpan<char> fen )
}

//applies side to move from FEN. I decided to store it as an int for ease of extracting data from arrays.
result.SideToMove = fen[split[1]][0] == 'w' ? 0 : 1;
result.SideToMove = fen[split[1]][0] == 'w' ? WHITE : BLACK;

//applies castle rights from FEN. I set them to one here, but remember that .GetBitValue() from bitboard does not have to return 0 or 1, cuz output is not shifted.
ReadOnlySpan<char> castleRights = fen[split[2]];
Expand All @@ -76,17 +76,16 @@ public static BoardData Create( ReadOnlySpan<char> fen )
break;

if (castleRights[i] == 'Q')
result.CanWhiteCastleQueenSide = 1;
result.CanWhiteCastleQueenSide = true;
else if (castleRights[i] == 'K')
result.CanWhiteCastleKingSide = 1;
result.CanWhiteCastleKingSide = true;
else if (castleRights[i] == 'q')
result.CanBlackCastleQueenSide = 1;
result.CanBlackCastleQueenSide = true;
else if (castleRights[i] == 'k')
result.CanBlackCastleKingSide = 1;
result.CanBlackCastleKingSide = true;
}

result.IsWhiteKingInCheck = result.IsSquareAttacked( result.GetPieceBitboard( 5, 0 ).LsbIndex, 0 ) ? 1 : 0;
result.IsBlackKingInCheck = result.IsSquareAttacked( result.GetPieceBitboard( 5, 1 ).LsbIndex, 1 ) ? 1 : 0;
result.IsSideToMoveInCheck = result.IsSquareAttacked(result.GetPieceBitboard(5, result.SideToMove).LsbIndex, result.SideToMove);

//applies en passant square (https://www.chessprogramming.org/En_passant)
ReadOnlySpan<char> enPassant = fen[split[3]];
Expand Down
54 changes: 0 additions & 54 deletions Engine/Data/Bitboards/BitboardInt.cs

This file was deleted.

4 changes: 2 additions & 2 deletions Engine/EngineCredentials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static class EngineCredentials
public static string Version => $"{MajorPatchNumber}.{FeatureCountSiceLastMajorPatch}.{CommitsSinceLastFeature}";

private const int MajorPatchNumber = 0;
private const int FeatureCountSiceLastMajorPatch = 5;
private const int CommitsSinceLastFeature = 4;
private const int FeatureCountSiceLastMajorPatch = 7;
private const int CommitsSinceLastFeature = 6;
}
}
12 changes: 12 additions & 0 deletions Engine/Globals.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
global using static Engine.Globals;

namespace Engine;

public class Globals
{
public const int WHITE = 0;
public const int BLACK = 1;

public const int INFINITY = 777_777;
public const int MATE_SCORE = 777_700;
}
Loading