From 5e57ce674dab7c45b454b031cee84fd10ba8d56f Mon Sep 17 00:00:00 2001 From: H.G.Muller Date: Sat, 17 Feb 2018 14:23:29 +0100 Subject: [PATCH] Remember 12 bits of eval in repeat keys The repeat key is a combination of the hash key for the board position, and the evaluation. This is used for detecting pseudo-repeats, where the eval part is then used to forbid material-buring loops. But burning a Queen changes the eval by 2*600 = 1200 points, and 12 bits are needed to store that without (signed!) overflow. As only 11 bits were used, loops burning a Queen were considered winning. This would still be the case for loops burning two Queens. Increasing the number of eval bits to 12 has increased the probability for a falsely detected pseudo-repetition to one in a million, which still seems acceptable. --- dropper.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dropper.c b/dropper.c index 34e11f8..959a50a 100644 --- a/dropper.c +++ b/dropper.c @@ -574,7 +574,7 @@ printf("# variant %d: %s\n", v, variants[v].name); for(i=0; *ip >= 0; i++) pieceValues[WHITE+i] = pieceValues[BLACK+i] = *ip++; // basic for(i=16,ip++; *ip >= 0; i++) pieceValues[WHITE+i] = pieceValues[BLACK+i] = *ip++; // promoted for(i=0, ip++; *ip >= 0; i++) handVal[WHITE+i] = handVal[BLACK+i] = *ip++; // in hand - pawn = 2*handVal[WHITE] << 21; // used for detection of material-loosing loops + pawn = 2*handVal[WHITE] << 20; // used for detection of material-loosing loops for(i=0; i<16; i++) { int demoted = dropType[handSlot[WHITE+i+16]]-1; // piece type after demotion (could be Pawn, in Chess) handVal[WHITE+i+16] = handVal[BLACK+i+16] = pieceValues[WHITE+i+16] + handVal[demoted]; // gain by capturing promoted piece @@ -1331,10 +1331,10 @@ Search (int stm, int alpha, int beta, StackFrame *ff, int depth, int reduction, // repetition checking int index = (unsigned int)f.newKey >> 24 ^ stm << 2; // uses high byte of low (= hands-free) key - while(repKey[index] && (repKey[index] ^ (int)f.newKey) & 0x1FFFFF) index++; + while(repKey[index] && (repKey[index] ^ (int)f.newKey) & 0xFFFFF) index++; int oldRepKey = repKey[index], oldRepDep = repDep[index]; if(oldRepKey && ff->mutation != -2) { // key present in table: (quasi-)repetition - int gain = (f.newEval << 21) - (repKey[index] & 0xFFE00000); + int gain = (f.newEval << 20) - (repKey[index] & 0xFFF00000); if(gain == 0) { // true repeat score = 0; if(perpLoses) { // repetitions not always draw @@ -1350,8 +1350,8 @@ Search (int stm, int alpha, int beta, StackFrame *ff, int depth, int reduction, } } - else if(gain == pawn || gain >= (400<<21)) score = INF-1; // quasi-repeat with extra piece in hand - else if(gain == -pawn || gain <= (-400<<21)) score = 1-INF; // or with one piece less + else if(gain == pawn || gain >= (400<<20)) score = INF-1; // quasi-repeat with extra piece in hand + else if(gain == -pawn || gain <= (-400<<20)) score = 1-INF; // or with one piece less else goto search;// traded one hand piece for another; could still lead somewhere f.lim = score; f.depth = (score >= beta ? highDepth+1 : iterDepth); // minimum required depth *pvPtr = 0; // fake that daughter returned empty PV @@ -1361,7 +1361,7 @@ Search (int stm, int alpha, int beta, StackFrame *ff, int depth, int reduction, lmr = (curMove >= m.late) + (curMove >= m.drops); f.tpGain = f.newEval + ff->pstEval; // material gain in last two ply if(ply==0 && randomize && moveNr < 10) ran = (alpha > INF-100 || alpha <-INF+100 ? 0 : (f.newKey*ranKey>>24 & 31)- 16); - repKey[index] = (int)f.newKey & 0x1FFFFF | f.newEval << 21; repDep[index] = ply + moveNr; // remember position + repKey[index] = (int)f.newKey & 0xFFFFF | f.newEval << 20; repDep[index] = ply + moveNr; // remember position // recursion deprec[ply] = (f.checker != CK_NONE ? f.checker : 0)<<24 | maxDepth<<16 | depth<< 8 | iterDepth; path[ply++] = moveStack[curMove] & 0xFFFF; score = -Search(stm, -beta, -alpha+ran, &f, iterDepth-1, lmr, highDepth); @@ -1689,8 +1689,8 @@ RootMakeMove(int move) if(moveNr >= 19 && !perpLoses) PST[WHITE+1] = knightPST, PST[BLACK+1] = knightPST + 11; // store in game history hash table index = (unsigned int)undoInfo.newKey >> 24 ^ stm << 2; // uses high byte of low (= hands-free) key - while(repKey[index] && (repKey[index] ^ (int)undoInfo.newKey) & 0x1FFFFF) index++; // find empty slot - repKey[index] = (int)undoInfo.newKey & 0x1FFFFF | undoInfo.newEval << 21; // remember position + while(repKey[index] && (repKey[index] ^ (int)undoInfo.newKey) & 0xFFFFF) index++; // find empty slot + repKey[index] = (int)undoInfo.newKey & 0xFFFFF | undoInfo.newEval << 20; // remember position repDep[index] = moveNr; stm ^= COLOR; moveNr++; return 1; -- 1.7.0.4