Treat Betza-defined e.p. capture
[xboard.git] / backend.c
index 2a34146..f465f95 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1600,6 +1600,7 @@ InitBackEnd3 P((void))
     char buf[MSG_SIZ];
     int err, len;
 
+    ParseFeatures(appData.features[0], &first);
     if(!appData.icsActive && !appData.noChessProgram && !appData.matchMode &&                         // mode involves only first engine
        !strcmp(appData.variant, "normal") &&                                                          // no explicit variant request
         appData.NrRanks == -1 && appData.NrFiles == -1 && appData.holdingsSize == -1 &&               // no size overrides requested
@@ -4301,7 +4302,7 @@ read_from_ics (InputSourceRef isr, VOIDSTAR closure, char *data, int count, int
 
     } else if (count == 0) {
        RemoveInputSource(isr);
-        DisplayFatalError(_("Connection closed by ICS"), 0, 0);
+        DisplayFatalError(_("Connection closed by ICS"), 0, 6666);
     } else {
        DisplayFatalError(_("Error reading from ICS"), error, 1);
     }
@@ -6498,7 +6499,7 @@ SendBoard (ChessProgramState *cps, int moveNum)
        * deprecated "black" command.
        */
       if (!WhiteOnMove(moveNum)) // [HGM] but better a deprecated command than an illegal move...
-        SendToProgram(boards[0][1][BOARD_LEFT] == WhitePawn ? "a2a3\n" : "black\n", cps);
+        SendToProgram(boards[0][1][BOARD_LEFT] == WhitePawn && !pieceDesc[WhitePawn] ? "a2a3\n" : "black\nforce\n", cps);
 
       if(!cps->extendedEdit) left = BOARD_LEFT, right = BOARD_RGHT; // only board proper
 
@@ -7945,6 +7946,7 @@ LeftClick (ClickType clickType, int xPix, int yPix)
        if(saveAnimate && !appData.animate && currentMove != oldMove && // drag-move was performed
           Explode(boards[currentMove-1], fromX, fromY, toX, toY))
            DrawPosition(TRUE, boards[currentMove]);
+       else DrawPosition(FALSE, NULL);
        fromX = fromY = -1;
        flashing = 0;
     }
@@ -10211,14 +10213,14 @@ ParseGameHistory (char *game)
 void
 ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
 {
-  ChessSquare captured = board[toY][toX], piece, pawn, king, killed, killed2; int p, rookX, oldEP, epRank, berolina = 0;
+  ChessSquare captured = board[toY][toX], piece, pawn, king, killed, killed2; int p, rookX, oldEP, epRank, epFile, berolina = 0;
   int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 3 : 1;
 
     /* [HGM] compute & store e.p. status and castling rights for new position */
     /* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */
 
       if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A;
-      oldEP = (signed char)board[EP_FILE]; epRank = board[EP_RANK];
+      oldEP = (signed char)board[EP_FILE]; epRank = board[EP_RANK]; epFile = board[EP_FILE];
       board[EP_STATUS] = EP_NONE;
       board[EP_FILE] = board[EP_RANK] = 100;
 
@@ -10252,6 +10254,13 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
       }
 
       pawn = board[fromY][fromX];
+      if(pieceDesc[pawn] && strchr(pieceDesc[pawn], 'e')) { // piece with user-defined e.p. capture
+       if(captured == EmptySquare && toX == epFile && (toY == (epRank & 127) || toY + (pawn < BlackPawn ? -1 : 1) == epRank - 128)) {
+           captured = board[epRank + (pawn < BlackPawn ? -1 : 1)][oldEP & berolina-1]; // remove victim
+           board[epRank + (pawn < BlackPawn ? -1 : 1)][oldEP & berolina-1] = EmptySquare;
+           pawn = EmptySquare; // kludge to suppress old e.p. code
+       }
+      }
       if( pawn == WhiteLance || pawn == BlackLance ) {
            if( gameInfo.variant != VariantSuper && gameInfo.variant != VariantChu ) {
                if(gameInfo.variant == VariantSpartan) board[EP_STATUS] = EP_PAWN_MOVE; // in Spartan no e.p. rights must be set
@@ -11214,7 +11223,7 @@ CreateTourney (char *name)
 int
 NamesToList (char *names, char **engineList, char **engineMnemonic, char *group)
 {
-    char buf[MSG_SIZ], *p, *q;
+    char buf[2*MSG_SIZ], *p, *q;
     int i=1, header, skip, all = !strcmp(group, "all"), depth = 0;
     insert = names; // afterwards, this global will point just after last retrieved engine line or group end in the 'names'
     skip = !all && group[0]; // if group requested, we start in skip mode
@@ -11671,7 +11680,7 @@ GameEnds (ChessMove result, char *resultDetails, int whosays)
               && result != GameIsDrawn)
            {   int i, j, k=0, oppoKings = 0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);
                for(j=BOARD_LEFT; j<BOARD_RGHT; j++) for(i=0; i<BOARD_HEIGHT; i++) {
-                       int p = (signed char)boards[forwardMostMove][i][j] - color;
+                       int p = (int)boards[forwardMostMove][i][j] - color;
                        if(p >= 0 && p <= (int)WhiteKing) k++;
                        oppoKings += (p + color == WhiteKing + BlackPawn - color);
                }
@@ -14876,7 +14885,9 @@ MachineWhiteEvent ()
 
        safeStrCpy(bookMove, "move ", sizeof(bookMove)/sizeof(bookMove[0]));
        strcat(bookMove, bookHit);
-       HandleMachineMove(bookMove, &first);
+       savedMessage = bookMove; // args for deferred call
+       savedState = &first;
+       ScheduleDelayedEvent(DeferredBookMove, 1);
     }
 }
 
@@ -14951,7 +14962,9 @@ MachineBlackEvent ()
 
        safeStrCpy(bookMove, "move ", sizeof(bookMove)/sizeof(bookMove[0]));
        strcat(bookMove, bookHit);
-       HandleMachineMove(bookMove, &first);
+       savedMessage = bookMove; // args for deferred call
+       savedState = &first;
+       ScheduleDelayedEvent(DeferredBookMove, 1);
     }
 }
 
@@ -19065,9 +19078,10 @@ int transparency[2];
 void
 LoadTheme ()
 {
-    char *p, *q, buf[MSG_SIZ];
+#define BUF_SIZ (2*MSG_SIZ)
+    char *p, *q, buf[BUF_SIZ];
     if(engineLine && engineLine[0]) { // a theme was selected from the listbox
-       snprintf(buf, MSG_SIZ, "-theme %s", engineLine);
+       snprintf(buf, BUF_SIZ, "-theme %s", engineLine);
        ParseArgsFromString(buf);
        ActivateTheme(TRUE); // also redo colors
        return;
@@ -19077,46 +19091,48 @@ LoadTheme ()
     {
        int len;
        q = appData.themeNames;
-       snprintf(buf, MSG_SIZ, "\"%s\"", nickName);
+       snprintf(buf, BUF_SIZ, "\"%s\"", nickName);
       if(appData.useBitmaps) {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ubt true -lbtf \"%s\" -dbtf \"%s\" -lbtm %d -dbtm %d",
-               appData.liteBackTextureFile, appData.darkBackTextureFile,
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ubt true -lbtf \"%s\"",
+               Shorten(appData.liteBackTextureFile));
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -dbtf \"%s\" -lbtm %d -dbtm %d",
+               Shorten(appData.darkBackTextureFile),
                appData.liteBackTextureMode,
                appData.darkBackTextureMode );
       } else {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ubt false");
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ubt false");
       }
       if(!appData.useBitmaps || transparency[0]) {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -lsc %s", Col2Text(2) ); // lightSquareColor
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -lsc %s", Col2Text(2) ); // lightSquareColor
       }
       if(!appData.useBitmaps || transparency[1]) {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -dsc %s", Col2Text(3) ); // darkSquareColor
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -dsc %s", Col2Text(3) ); // darkSquareColor
       }
       if(appData.useBorder) {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ub true -border \"%s\"",
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ub true -border \"%s\"",
                appData.border);
       } else {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ub false");
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ub false");
       }
       if(appData.useFont) {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -upf true -pf \"%s\" -fptc \"%s\" -fpfcw %s -fpbcb %s",
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -upf true -pf \"%s\" -fptc \"%s\" -fpfcw %s -fpbcb %s",
                appData.renderPiecesWithFont,
                appData.fontToPieceTable,
                Col2Text(9),    // appData.fontBackColorWhite
                Col2Text(10) ); // appData.fontForeColorBlack
       } else {
-       snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -upf false");
+       snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -upf false");
        if(appData.pieceDirectory[0]) {
-         snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -pid \"%s\"", appData.pieceDirectory);
+         snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -pid \"%s\"", Shorten(appData.pieceDirectory));
          if(appData.trueColors != 2) // 2 is a kludge to suppress this in WinBoard
-           snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -trueColors %s", appData.trueColors ? "true" : "false");
+           snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -trueColors %s", appData.trueColors ? "true" : "false");
        }
        if(!appData.pieceDirectory[0] || !appData.trueColors)
-         snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -wpc %s -bpc %s",
+         snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -wpc %s -bpc %s",
                Col2Text(0),   // whitePieceColor
                Col2Text(1) ); // blackPieceColor
       }
-      snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -hsc %s -phc %s\n",
+      snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -hsc %s -phc %s\n",
                Col2Text(4),   // highlightSquareColor
                Col2Text(5) ); // premoveHighlightColor
        appData.themeNames = malloc(len = strlen(q) + strlen(buf) + 1);