Implement Makruk counting rules
[xboard.git] / backend.c
index ad19851..6d29691 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -4741,7 +4741,13 @@ ParseBoard12 (char *string)
     boards[moveNum][EP_STATUS] = EP_NONE;
     if(str[0] == 'P') boards[moveNum][EP_STATUS] = EP_PAWN_MOVE;
     if(strchr(move_str, 'x')) boards[moveNum][EP_STATUS] = EP_CAPTURE;
-    if(double_push !=  -1) boards[moveNum][EP_STATUS] = double_push + BOARD_LEFT;
+    if(double_push !=  -1) {
+       int dir = WhiteOnMove(moveNum) ? 1 : -1, last = BOARD_HEIGHT-1;
+       boards[moveNum][EP_FILE] = // also set new e.p. variables
+       boards[moveNum][EP_STATUS] = double_push + BOARD_LEFT;
+       boards[moveNum][EP_RANK] = (last + 3*dir)/2;
+       boards[moveNum][LAST_TO] = 128*(last + dir) + boards[moveNum][EP_FILE];
+    } else boards[moveNum][EP_FILE] = boards[moveNum][EP_RANK] = 100;
 
 
     if (ics_getting_history == H_GOT_REQ_HEADER ||
@@ -6342,10 +6348,11 @@ InitPosition (int redraw)
       shuffleOpenings = 1;
       break;
     case VariantNoCastle:
-      pieces = FIDEArray;
-      nrCastlingRights = 0;
       /* !!?unconstrained back-rank shuffle */
       shuffleOpenings = 1;
+    case VariantSuicide:
+      pieces = FIDEArray;
+      nrCastlingRights = 0;
       break;
     }
 
@@ -8500,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