Implement mate killers
authorH.G.Muller <hgm@hgm-xboard.(none)>
Tue, 7 Feb 2017 19:23:12 +0000 (20:23 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Tue, 7 Feb 2017 20:03:13 +0000 (21:03 +0100)
Moves that force mate aftera check evasion are remembered in a mateKillers
table, indexed by the preceding evasion. Such moves are tried in QS as
reply to the same evasion. This should make it more difficult to push
tsume mates over the horizon by spite checks in a hisshi situation.

dropper.c

index 87c0d35..155be56 100644 (file)
--- a/dropper.c
+++ b/dropper.c
@@ -71,7 +71,7 @@ int handVal[96], rawGain[97];
 unsigned int moveStack[500*MAXPLY];
 int killers[MAXPLY][2];
 int path[MAXPLY], deprec[MAXPLY];
-int history[1<<16];
+int history[1<<16], mateKillers[1<<17];
 unsigned char checkHist[MAXMOVES+MAXPLY];
 int repKey[512+20];
 
@@ -703,7 +703,7 @@ typedef struct {
     unsigned char fromSqr, toSqr, captSqr, epSqr, rookSqr, rights;
     signed char fromPiece, toPiece, victim, savePiece, rook, mutation;
     int pstEval, newEval, bulk;
-    int move, depth;
+    int move, wholeMove, depth;
     int checker, checkDir, checkDist, xking;
 } StackFrame;
 
@@ -1019,6 +1019,7 @@ MakeMove (StackFrame *f, int move)
     int to, stm;
     f->fromSqr = move >> 8 & 255;
     to = move & 255;
+    f->wholeMove = move;
     f->toSqr = f->captSqr = toDecode[to];                               // real to-square for to-encoded special moves
     f->fromPiece = board[f->fromSqr];                                   // occupant or (for drops) complemented holdings count
     if(f->checker != CK_NONE && NonEvade(f)) return 0;                  // abort if move did not evade existing check
@@ -1213,6 +1214,12 @@ if(hashMove && board[hashMove>>8&255] == 0) {char s[100];sprintf(s,"bad hash mov
     }
     if(hashMove) moveStack[--m.firstMove] = hashMove; // put hash move in front of list (duplicat!)
     if(f.checker != CK_NONE) moveSP = m.drops = m.castlings; // clip off castlings when in check
+    if(ff->checker != CK_NONE) { // last move was evasion; see if we have counter move
+       int move = mateKillers[(ff->wholeMove & 0xFFFF) + (stm - WHITE << 11)];
+       if(move && (move>>16 & 0xFF) == f.xking && (move>>24 & 0xFF) == board[toDecode[move & 0xFF]] && PseudoLegal(stm, move)) { // counter move is pseudo-legal and matches position
+           moveStack[moveSP++] = moveStack[m.nonCapts]; moveStack[m.nonCapts] = move & 0xFFFF; m.late = ++m.nonCapts; // make room and put with captures (lowest sort key)
+       }
+    }
 
     do { // IID loop
        int curMove, highDepth;
@@ -1315,6 +1322,8 @@ printf("%d:%d:%d %2d. %08x %c%d%c%d %6d %6d %6d\n",ply,depth,iterDepth,curMove,m
                    int *tail;
                    alpha = score; bestNr = curMove;
                    history[moveStack[curMove] & 0xFFFF] += iterDepth*iterDepth;
+                   if(score > INF-100 && curMove >= m.nonCapts)
+                       mateKillers[(ff->wholeMove & 0xFFFF) + (stm - WHITE << 11)] = moveStack[curMove] & 0xFFFF | f.xking << 16 | board[f.toSqr] << 24; // store mate killers
                    if(score >= beta) { // beta cutoff
                        if(curMove >= m.nonCapts && moveStack[curMove] != killers[ply][1])
                            killers[ply][0] = killers[ply][1], killers[ply][1] = moveStack[curMove];
@@ -1730,6 +1739,7 @@ main ()
 
       nodeCount = forceMove = undoInfo.move = abortFlag = 0; ReadClock(1);
       for(i=0;i<1<<16;i++) history[i] = 0; //>>= 1;
+      for(i=0;i<1<<17;i++) mateKillers[i] = 0;
       score = Search(stm^COLOR, -INF, INF, &undoInfo, maxDepth, 0, maxDepth);
 
       if(!undoInfo.move) {             // no move, game apparently ended