summaryrefslogtreecommitdiff
path: root/src/poshash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/poshash.c')
-rw-r--r--src/poshash.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/poshash.c b/src/poshash.c
new file mode 100644
index 0000000..e8f09b5
--- /dev/null
+++ b/src/poshash.c
@@ -0,0 +1,276 @@
+/*++
+
+Copyright (c) Scott Gasch
+
+Module Name:
+
+ poshash.c
+
+Abstract:
+
+ A hash table of information about positions.
+
+Author:
+
+ Scott Gasch (SGasch) 11 Nov 2006
+
+Revision History:
+
+--*/
+
+#include "chess.h"
+
+#define NUM_POSITION_HASH_ENTRIES (1048576) // 16Mb
+POSITION_HASH_ENTRY g_PositionHash[NUM_POSITION_HASH_ENTRIES];
+
+#ifdef MP
+#define NUM_POSITION_HASH_LOCKS (512)
+volatile static ULONG g_uPositionHashLocks[NUM_POSITION_HASH_LOCKS];
+#define POSITION_HASH_IS_LOCKED(x) ((g_uPositionHashLocks[(x)]) != 0)
+#define LOCK_POSITION_HASH(x) \
+ AcquireSpinLock(&(g_uPositionHashLocks[(x)])); \
+ ASSERT(POSITION_HASH_IS_LOCKED(x))
+#define UNLOCK_POSITION_HASH(x) \
+ ASSERT(POSITION_HASH_IS_LOCKED(x)); \
+ ReleaseSpinLock(&(g_uPositionHashLocks[(x)]))
+#else
+#define POSITION_HASH_IS_LOCKED(x)
+#define LOCK_HASH(x)
+#define UNLOCK_HASH(x)
+#endif
+
+void
+InitializePositionHashSystem(void)
+{
+ memset(&g_PositionHash, 0, sizeof(g_PositionHash));
+#ifdef MP
+ memset(&g_uPositionHashLocks, 0, sizeof(g_uPositionHashLocks));
+#endif
+}
+
+void
+CleanupPositionHashSystem(void)
+{
+ ; // do nothing
+}
+
+static INLINE UINT64 PositionToSignatureIgnoringMove(POSITION *pos)
+{
+ return((pos->u64NonPawnSig ^ pos->u64PawnSig) >> 1);
+}
+
+// Note: sig must be pre-shifted to ignore the side-to-move bit.
+static INLINE ULONG PositionSigToHashPosition(UINT64 u64Sig)
+{
+ ULONG u = (ULONG)u64Sig;
+ u &= (NUM_POSITION_HASH_ENTRIES - 1);
+ ASSERT(u < NUM_POSITION_HASH_ENTRIES);
+ return u;
+}
+
+#ifdef MP
+static INLINE ULONG HashPositionToLockNumber(ULONG u)
+{
+ u &= (NUM_POSITION_HASH_LOCKS - 1);
+ ASSERT(u < NUM_POSITION_HASH_LOCKS);
+ return u;
+}
+#endif
+
+void
+StoreEnprisePiece(POSITION *pos, COOR cSquare)
+{
+ UINT64 u64Sig = PositionToSignatureIgnoringMove(pos);
+ ULONG uEntry = PositionSigToHashPosition(u64Sig);
+ POSITION_HASH_ENTRY *pHash = &(g_PositionHash[uEntry]);
+ PIECE p = pos->rgSquare[cSquare].pPiece;
+ ULONG uColor = GET_COLOR(p);
+#ifdef MP
+ ULONG uLock = HashPositionToLockNumber(uEntry);
+ LOCK_POSITION_HASH(uLock);
+#endif
+ ASSERT(p && IS_VALID_PIECE(p));
+ ASSERT(!IS_PAWN(p));
+ ASSERT(CAN_FIT_IN_UCHAR(cSquare));
+ ASSERT(IS_ON_BOARD(cSquare));
+ pHash->cEnprise[uColor] = (UCHAR)cSquare;
+ ASSERT(pHash->uEnpriseCount[uColor] < 16);
+ pHash->uEnpriseCount[uColor] += 1;
+ if (pHash->u64Sig != u64Sig)
+ {
+ pHash->u64Sig = u64Sig;
+ pHash->uEnpriseCount[uColor] = 1;
+ pHash->cTrapped[uColor] = ILLEGAL_COOR;
+ uColor = FLIP(uColor);
+ pHash->cEnprise[uColor] = ILLEGAL_COOR;
+ pHash->cTrapped[uColor] = ILLEGAL_COOR;
+ pHash->uEnpriseCount[uColor] = 0;
+ }
+#ifdef MP
+ UNLOCK_POSITION_HASH(uLock);
+#endif
+}
+
+void
+StoreTrappedPiece(POSITION *pos, COOR cSquare)
+{
+ UINT64 u64Sig = PositionToSignatureIgnoringMove(pos);
+ ULONG uEntry = PositionSigToHashPosition(u64Sig);
+ POSITION_HASH_ENTRY *pHash = &(g_PositionHash[uEntry]);
+ PIECE p = pos->rgSquare[cSquare].pPiece;
+ ULONG uColor = GET_COLOR(p);
+#ifdef MP
+ ULONG uLock = HashPositionToLockNumber(uEntry);
+ LOCK_POSITION_HASH(uLock);
+#endif
+ ASSERT(p && IS_VALID_PIECE(p));
+ ASSERT(!IS_PAWN(p));
+ ASSERT(CAN_FIT_IN_UCHAR(cSquare));
+ ASSERT(IS_ON_BOARD(cSquare));
+ pHash->cTrapped[uColor] = cSquare;
+ if (pHash->u64Sig != u64Sig)
+ {
+ pHash->u64Sig = u64Sig;
+ pHash->cEnprise[uColor] = ILLEGAL_COOR;
+ pHash->uEnpriseCount[uColor] = 0;
+ uColor = FLIP(uColor);
+ pHash->cEnprise[uColor] = ILLEGAL_COOR;
+ pHash->cTrapped[uColor] = ILLEGAL_COOR;
+ pHash->uEnpriseCount[uColor] = 0;
+ }
+#ifdef MP
+ UNLOCK_POSITION_HASH(uLock);
+#endif
+}
+
+COOR
+GetEnprisePiece(POSITION *pos, ULONG uSide)
+{
+ UINT64 u64Sig = PositionToSignatureIgnoringMove(pos);
+ ULONG uEntry = PositionSigToHashPosition(u64Sig);
+ POSITION_HASH_ENTRY *pHash = &(g_PositionHash[uEntry]);
+ COOR c = ILLEGAL_COOR;
+#ifdef MP
+ ULONG uLock = HashPositionToLockNumber(uEntry);
+ LOCK_POSITION_HASH(uLock);
+#endif
+ if (pHash->u64Sig == u64Sig)
+ {
+ c = pHash->cEnprise[uSide];
+ }
+#ifdef MP
+ UNLOCK_POSITION_HASH(uLock);
+#endif
+ return c;
+}
+
+COOR
+GetTrappedPiece(POSITION *pos, ULONG uSide)
+{
+ UINT64 u64Sig = PositionToSignatureIgnoringMove(pos);
+ ULONG uEntry = PositionSigToHashPosition(u64Sig);
+ POSITION_HASH_ENTRY *pHash = &(g_PositionHash[uEntry]);
+ COOR c = ILLEGAL_COOR;
+#ifdef MP
+ ULONG uLock = HashPositionToLockNumber(uEntry);
+ LOCK_POSITION_HASH(uLock);
+#endif
+ if (pHash->u64Sig == u64Sig)
+ {
+ c = pHash->cTrapped[uSide];
+ }
+#ifdef MP
+ UNLOCK_POSITION_HASH(uLock);
+#endif
+ return c;
+}
+
+FLAG
+SideCanStandPat(POSITION *pos, ULONG uSide)
+{
+ UINT64 u64Sig = PositionToSignatureIgnoringMove(pos);
+ ULONG uEntry = PositionSigToHashPosition(u64Sig);
+ POSITION_HASH_ENTRY *pHash = &(g_PositionHash[uEntry]);
+ FLAG fStand = TRUE;
+#ifdef MP
+ ULONG uLock = HashPositionToLockNumber(uEntry);
+ LOCK_POSITION_HASH(uLock);
+#endif
+ if (pHash->u64Sig == u64Sig)
+ {
+ fStand = ((pHash->cTrapped[uSide] == ILLEGAL_COOR) &&
+ (pHash->uEnpriseCount[uSide] < 2));
+ }
+#ifdef MP
+ UNLOCK_POSITION_HASH(uLock);
+#endif
+ return fStand;
+}
+
+ULONG
+ValueOfMaterialInTroubleDespiteMove(POSITION *pos, ULONG uSide)
+{
+ UINT64 u64Sig = PositionToSignatureIgnoringMove(pos);
+ ULONG uEntry = PositionSigToHashPosition(u64Sig);
+ POSITION_HASH_ENTRY *pHash = &(g_PositionHash[uEntry]);
+ ULONG u = 0;
+ COOR c;
+#ifdef MP
+ ULONG uLock = HashPositionToLockNumber(uEntry);
+ LOCK_POSITION_HASH(uLock);
+#endif
+ if (pHash->u64Sig == u64Sig)
+ {
+ if (pHash->uEnpriseCount[uSide] > 1)
+ {
+ c = pHash->cEnprise[uSide];
+ ASSERT(IS_ON_BOARD(c));
+ u = PIECE_VALUE(pos->rgSquare[c].pPiece);
+ ASSERT(u);
+ }
+ c = pHash->cTrapped[uSide];
+ if (IS_ON_BOARD(c))
+ {
+ u = MAXU(u, PIECE_VALUE(pos->rgSquare[c].pPiece));
+ ASSERT(u);
+ }
+ }
+#ifdef MP
+ UNLOCK_POSITION_HASH(uLock);
+#endif
+ return u;
+}
+
+ULONG
+ValueOfMaterialInTroubleAfterNull(POSITION *pos, ULONG uSide)
+{
+ UINT64 u64Sig = PositionToSignatureIgnoringMove(pos);
+ ULONG uEntry = PositionSigToHashPosition(u64Sig);
+ POSITION_HASH_ENTRY *pHash = &(g_PositionHash[uEntry]);
+ ULONG u = 0;
+ COOR c;
+#ifdef MP
+ ULONG uLock = HashPositionToLockNumber(uEntry);
+ LOCK_POSITION_HASH(uLock);
+#endif
+ if (pHash->u64Sig == u64Sig)
+ {
+ if (pHash->uEnpriseCount[uSide])
+ {
+ c = pHash->cEnprise[uSide];
+ ASSERT(IS_ON_BOARD(c));
+ u += PIECE_VALUE(pos->rgSquare[c].pPiece);
+ ASSERT(u);
+ }
+ c = pHash->cTrapped[uSide];
+ if (IS_ON_BOARD(c))
+ {
+ u = MAXU(PIECE_VALUE(pos->rgSquare[c].pPiece), u);
+ ASSERT(u);
+ }
+ }
+#ifdef MP
+ UNLOCK_POSITION_HASH(uLock);
+#endif
+ return u;
+}