Add feature-override options
[xboard.git] / backend.c
index bac20d8..ca3e342 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -834,6 +834,7 @@ InitEngine(ChessProgramState *cps, int n)
       }
 
     InitEngineUCI( installDir, cps );  // [HGM] moved here from winboard.c, to make available in xboard
+    ParseFeatures(appData.featureDefaults, cps);
 }
 
 ChessProgramState *savCps;
@@ -5136,7 +5137,7 @@ Sweep(int step)
        else if((int)promoSweep == -1) promoSweep = WhiteKing;
        else if(promoSweep == BlackPawn && step < 0) promoSweep = WhitePawn;
        else if(promoSweep == WhiteKing && step > 0) promoSweep = BlackKing;
-       if(!step) step = 1;
+       if(!step) step = -1;
     } while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn ||
            appData.testLegality && (promoSweep == king ||
            gameInfo.variant == VariantShogi && promoSweep != PROMOTED last && last != PROMOTED promoSweep && last != promoSweep));
@@ -8118,10 +8119,12 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
       return; // [HGM] This return was missing, causing option features to be recognized as non-compliant commands!
     }
 
-    if (!appData.testLegality && !strncmp(message, "setup ", 6)) { // [HGM] allow first engine to define opening position
+    if ((!appData.testLegality || gameInfo.variant == VariantFairy) && 
+                                       !strncmp(message, "setup ", 6)) { // [HGM] allow first engine to define opening position
       int dummy, s=6; char buf[MSG_SIZ];
-      if(appData.icsActive || forwardMostMove != 0 || cps != &first || startedFromSetupPosition) return;
+      if(appData.icsActive || forwardMostMove != 0 || cps != &first) return;
       if(sscanf(message, "setup (%s", buf) == 1) s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf);
+      if(startedFromSetupPosition) return;
       ParseFEN(boards[0], &dummy, message+s);
       DrawPosition(TRUE, boards[0]);
       startedFromSetupPosition = TRUE;
@@ -9537,6 +9540,7 @@ InitChessProgram(cps, setup)
     hintRequested = FALSE;
     bookRequested = FALSE;
 
+    ParseFeatures(appData.features[cps == &second], cps); // [HGM] allow user to overrule features
     /* [HGM] some new WB protocol commands to configure engine are sent now, if engine supports them */
     /*       moved to before sending initstring in 4.3.15, so Polyglot can delay UCI 'isready' to recepton of 'new' */
     if(cps->memSize) { /* [HGM] memory */
@@ -9923,6 +9927,7 @@ void SwapEngines(int n)
     SWAP(logo, p)
     SWAP(pgnName, p)
     SWAP(pvSAN, h)
+    SWAP(engOptions, p)
 }
 
 void
@@ -11283,13 +11288,13 @@ int QuickCompare(Board board, int *minCounts, int *maxCounts)
        for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
            if(board[r][f] != pieceType[quickBoard[(r<<4)+f]]) return FALSE;
        }
-       return TRUE;
+       break;
       case 2: // can have extra material on empty squares
        for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
            if(board[r][f] == EmptySquare) continue;
            if(board[r][f] != pieceType[quickBoard[(r<<4)+f]]) return FALSE;
        }
-       return TRUE;
+       break;
       case 3: // material with exact Pawn structure
        for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
            if(board[r][f] != WhitePawn && board[r][f] != BlackPawn) continue;
@@ -11297,14 +11302,14 @@ int QuickCompare(Board board, int *minCounts, int *maxCounts)
        } // fall through to material comparison
       case 4: // exact material
        for(r=0; r<EmptySquare; r++) if(counts[r] != maxCounts[r]) return FALSE;
-       return TRUE;
+       break;
       case 6: // material range with given imbalance
        for(r=0; r<BlackPawn; r++) if(counts[r] - minCounts[r] != counts[r+BlackPawn] - minCounts[r+BlackPawn]) return FALSE;
        // fall through to range comparison
       case 5: // material range
        for(r=0; r<EmptySquare; r++) if(counts[r] < minCounts[r] || counts[r] > maxCounts[r]) return FALSE;
-       return TRUE;
     }
+    return TRUE;
 }
 
 int QuickScan(Board board, Move *move)
@@ -11485,6 +11490,7 @@ int GameContainsPosition(FILE *f, ListGame *lg)
                fromY = DROP_RANK;
                toX = currentMoveString[2] - AAA;
                toY = currentMoveString[3] - ONE;
+               promoChar = 0;
                break;
        }
        // Move encountered; peform it. We need to shuttle between two boards, as even/odd index determines side to move
@@ -14224,6 +14230,8 @@ ForwardInner(target)
     if (gameMode == EditPosition)
       return;
 
+    MarkTargetSquares(1);
+
     if (gameMode == PlayFromGameFile && !pausing)
       PauseEvent();
 
@@ -14329,6 +14337,7 @@ BackwardInner(target)
                target, currentMove, forwardMostMove);
 
     if (gameMode == EditPosition) return;
+    MarkTargetSquares(1);
     if (currentMove <= backwardMostMove) {
        ClearHighlights();
        DrawPosition(full_redraw, boards[currentMove]);