Implement Makruk counting rules
authorH.G.Muller <hgm@hgm-xboard.(none)>
Wed, 22 Feb 2017 19:34:36 +0000 (20:34 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Wed, 22 Feb 2017 19:34:36 +0000 (20:34 +0100)
Adjudication is now performed based on the Makruk counting rules, assuming
the players count in the way most favorable for them. This means that when
the maximum count is N, the game is adjudicated draw immediately after the
Nth move since the counting could have started when the opponent is bared,
but only on the next move when not, to give him the opportunity to checkmate
when he was not counting. This adjudication is switched off if -ruleMoves
is set to a negative value, (normally this would be 0 in Makruk), and is
also dependent on legality testing being on.

backend.c

index 9281e7e..6d29691 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -8507,6 +8507,32 @@ Adjudicate (ChessProgramState *cps)
                           return 1;
                      }
                 } else moveCount = 6;
+
+                if(gameInfo.variant == VariantMakruk && // Makruk counting rules
+                  (nrW == 1 || nrB == 1 || nr[WhitePawn] + nr[BlackPawn] == 0)) { // which only kick in when pawnless or bare King
+                    int maxcnt, his, mine, c, wom = WhiteOnMove(forwardMostMove);
+                    count = forwardMostMove;
+                    while(count >= backwardMostMove) {
+                        int np = nr[WhitePawn] + nr[BlackPawn];
+                        if(wom) mine = nrW, his = nrB, c = BlackPawn;
+                        else    mine = nrB, his = nrW, c = WhitePawn;
+                        if(mine > 1 && np) { count++; break; }
+                        if(mine > 1) maxcnt = 64; else
+                        maxcnt = (nr[WhiteRook+c] > 1 ? 8 : nr[WhiteRook+c] ? 16 : nr[WhiteMan+c] > 1 ? 22 :
+                                                            nr[WhiteKnight+c] > 1 ? 32 : nr[WhiteMan+c] ? 44 : 64) - his - 1;
+                        while(boards[count][EP_STATUS] != EP_CAPTURE && count > backwardMostMove) count--; // seek previous character
+                        if(count == backwardMostMove) break;
+                        if(forwardMostMove - count >= 2*maxcnt + 1 - (mine == 1)) break;
+                        Count(boards[--count], nr, &nrW, &nrB, &staleW, &staleB, &bishopColor);
+                    }
+                    if(forwardMostMove - count >= 2*maxcnt + 1 - (mine == 1)) {
+                        boards[forwardMostMove][EP_STATUS] = EP_RULE_DRAW;
+                        if(canAdjudicate && appData.ruleMoves >= 0) {
+                            GameEnds( GameIsDrawn, "Xboard adjudication: counting rule", GE_XBOARD );
+                            return 1;
+                        }
+                    }
+                }
            }
 
        // Repetition draws and 50-move rule can be applied independently of legality testing