-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5bad766
commit 90e7079
Showing
5 changed files
with
207 additions
and
133 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/* | ||
* | ||
*/ | ||
|
||
using BenchmarkDotNet.Attributes; | ||
using Lynx.Model; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace Lynx.Benchmark; | ||
public class ZobristHash_Castle : BaseBenchmark | ||
{ | ||
public static IEnumerable<Position> Data => new[] { | ||
new Position(Constants.InitialPositionFEN), | ||
new Position(Constants.TrickyTestPositionFEN), | ||
new Position(Constants.TrickyTestPositionReversedFEN), | ||
new Position(Constants.CmkTestPositionFEN), | ||
new Position(Constants.ComplexPositionFEN), | ||
new Position(Constants.KillerTestPositionFEN), | ||
}; | ||
|
||
[Benchmark(Baseline = true)] | ||
[ArgumentsSource(nameof(Data))] | ||
public long Naive(Position position) => CalculateMethod(position.Castle); | ||
|
||
[Benchmark] | ||
[ArgumentsSource(nameof(Data))] | ||
public long Dictionary(Position position) => DictionaryMethod(position.Castle); | ||
|
||
[Benchmark] | ||
[ArgumentsSource(nameof(Data))] | ||
public long Switch(Position position) => SwitchMethod(position); | ||
|
||
private static readonly long[,] _table = Initialize(); | ||
|
||
private static readonly long WK_Hash = _table[(int)BoardSquare.a8, (int)Piece.p]; | ||
private static readonly long WQ_Hash = _table[(int)BoardSquare.b8, (int)Piece.p]; | ||
private static readonly long BK_Hash = _table[(int)BoardSquare.c8, (int)Piece.p]; | ||
private static readonly long BQ_Hash = _table[(int)BoardSquare.d8, (int)Piece.p]; | ||
|
||
private static readonly Dictionary<byte, long> _castleHashDictionary = new() | ||
{ | ||
[0] = 0, // - | - | ||
[(byte)CastlingRights.WK] = WK_Hash, // K | - | ||
[(byte)CastlingRights.WQ] = WQ_Hash, // Q | - | ||
[(byte)CastlingRights.BK] = BK_Hash, // - | k | ||
[(byte)CastlingRights.BQ] = BQ_Hash, // - | q | ||
|
||
[(byte)CastlingRights.WK | (byte)CastlingRights.WQ] = WK_Hash ^ WQ_Hash, // KQ | - | ||
[(byte)CastlingRights.WK | (byte)CastlingRights.BK] = WK_Hash ^ BK_Hash, // K | k | ||
[(byte)CastlingRights.WK | (byte)CastlingRights.BQ] = WK_Hash ^ BQ_Hash, // K | q | ||
[(byte)CastlingRights.WQ | (byte)CastlingRights.BK] = WQ_Hash ^ BK_Hash, // Q | k | ||
[(byte)CastlingRights.WQ | (byte)CastlingRights.BQ] = WQ_Hash ^ BQ_Hash, // Q | q | ||
[(byte)CastlingRights.BK | (byte)CastlingRights.BQ] = BK_Hash ^ BQ_Hash, // - | kq | ||
|
||
[(byte)CastlingRights.WK | (byte)CastlingRights.WQ | (byte)CastlingRights.BK] = WK_Hash ^ WQ_Hash ^ BK_Hash, // KQ | k | ||
[(byte)CastlingRights.WK | (byte)CastlingRights.WQ | (byte)CastlingRights.BQ] = WK_Hash ^ WQ_Hash ^ BQ_Hash, // KQ | q | ||
[(byte)CastlingRights.WK | (byte)CastlingRights.BK | (byte)CastlingRights.BQ] = WK_Hash ^ BK_Hash ^ BQ_Hash, // K | kq | ||
[(byte)CastlingRights.WQ | (byte)CastlingRights.BK | (byte)CastlingRights.BQ] = WQ_Hash ^ BK_Hash ^ BQ_Hash, // Q | kq | ||
|
||
[(byte)CastlingRights.WK | (byte)CastlingRights.WQ | (byte)CastlingRights.BK | (byte)CastlingRights.BQ] = // KQ | kq | ||
WK_Hash ^ WQ_Hash ^ BK_Hash ^ BQ_Hash | ||
}; | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
internal static long CalculateMethod(byte castle) | ||
{ | ||
long combinedHash = 0; | ||
|
||
if ((castle & (int)CastlingRights.WK) != default) | ||
{ | ||
combinedHash ^= _table[(int)BoardSquare.a8, (int)Piece.p]; // a8 | ||
} | ||
|
||
if ((castle & (int)CastlingRights.WQ) != default) | ||
{ | ||
combinedHash ^= _table[(int)BoardSquare.b8, (int)Piece.p]; // b8 | ||
} | ||
|
||
if ((castle & (int)CastlingRights.BK) != default) | ||
{ | ||
combinedHash ^= _table[(int)BoardSquare.c8, (int)Piece.p]; // c8 | ||
} | ||
|
||
if ((castle & (int)CastlingRights.BQ) != default) | ||
{ | ||
combinedHash ^= _table[(int)BoardSquare.d8, (int)Piece.p]; // d8 | ||
} | ||
|
||
return combinedHash; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static long SwitchMethod(Position position) | ||
{ | ||
return position.Castle switch | ||
{ | ||
0 => 0, // - | - | ||
|
||
(byte)CastlingRights.WK => WK_Hash, // K | - | ||
(byte)CastlingRights.WQ => WQ_Hash, // Q | - | ||
(byte)CastlingRights.BK => BK_Hash, // - | k | ||
(byte)CastlingRights.BQ => BQ_Hash, // - | q | ||
|
||
(byte)CastlingRights.WK | (byte)CastlingRights.WQ => WK_Hash ^ WQ_Hash, // KQ | - | ||
(byte)CastlingRights.WK | (byte)CastlingRights.BK => WK_Hash ^ BK_Hash, // K | k | ||
(byte)CastlingRights.WK | (byte)CastlingRights.BQ => WK_Hash ^ BQ_Hash, // K | q | ||
(byte)CastlingRights.WQ | (byte)CastlingRights.BK => WQ_Hash ^ BK_Hash, // Q | k | ||
(byte)CastlingRights.WQ | (byte)CastlingRights.BQ => WQ_Hash ^ BQ_Hash, // Q | q | ||
(byte)CastlingRights.BK | (byte)CastlingRights.BQ => BK_Hash ^ BQ_Hash, // - | kq | ||
|
||
(byte)CastlingRights.WK | (byte)CastlingRights.WQ | (byte)CastlingRights.BK => WK_Hash ^ WQ_Hash ^ BK_Hash, // KQ | k | ||
(byte)CastlingRights.WK | (byte)CastlingRights.WQ | (byte)CastlingRights.BQ => WK_Hash ^ WQ_Hash ^ BQ_Hash, // KQ | q | ||
(byte)CastlingRights.WK | (byte)CastlingRights.BK | (byte)CastlingRights.BQ => WK_Hash ^ BK_Hash ^ BQ_Hash, // K | kq | ||
(byte)CastlingRights.WQ | (byte)CastlingRights.BK | (byte)CastlingRights.BQ => WQ_Hash ^ BK_Hash ^ BQ_Hash, // Q | kq | ||
|
||
(byte)CastlingRights.WK | (byte)CastlingRights.WQ | (byte)CastlingRights.BK | (byte)CastlingRights.BQ => // KQ | kq | ||
WK_Hash ^ WQ_Hash ^ BK_Hash ^ BQ_Hash, | ||
|
||
_ => new() | ||
}; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static long DictionaryMethod(byte castle) => _castleHashDictionary[castle]; | ||
|
||
/// <summary> | ||
/// Initializes Zobrist table (long[64, 12]) | ||
/// </summary> | ||
/// <returns></returns> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static long[,] Initialize() | ||
{ | ||
var zobristTable = new long[64, 12]; | ||
var randomInstance = new Random(int.MaxValue); | ||
|
||
for (int squareIndex = 0; squareIndex < 64; ++squareIndex) | ||
{ | ||
for (int pieceIndex = 0; pieceIndex < 12; ++pieceIndex) | ||
{ | ||
zobristTable[squareIndex, pieceIndex] = randomInstance.NextInt64(); | ||
} | ||
} | ||
|
||
return zobristTable; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters