Enhancement of the way -autoLogo decides which logos to display
[xboard.git] / backend.c
index 891d3e0..0b1b144 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -749,6 +749,8 @@ InitBackEnd1()
     first.useFEN960 = FALSE; second.useFEN960 = FALSE;\r
     first.useOOCastle = TRUE; second.useOOCastle = TRUE;\r
     /* End of new features added by Tord. */\r
+    first.fenOverride  = appData.fenOverride1;\r
+    second.fenOverride = appData.fenOverride2;\r
 \r
     /* [HGM] time odds: set factor for each machine */\r
     first.timeOdds  = appData.firstTimeOdds;\r
@@ -2274,6 +2276,12 @@ read_from_ics(isr, closure, data, count, error)
                            nrAlph  += (parse[i] >= 'A' && parse[i] <= 'Z');\r
                        }\r
                        if(nrAlph < 9*nrDigit) { // if more than 10% digit we assume search info\r
+                           int depth=0; float score;\r
+                           if(sscanf(parse, "%f/%d", &score, &depth) == 2 && depth>0) {\r
+                               // [HGM] kibitz: save kibitzed opponent info for PGN and eval graph\r
+                               pvInfoList[forwardMostMove-1].depth = depth;\r
+                               pvInfoList[forwardMostMove-1].score = 100*score;\r
+                           }\r
                            OutputKibitz(suppressKibitz, parse);\r
                        } else {\r
                            char tmp[MSG_SIZ];\r
@@ -4753,7 +4761,7 @@ SendBoard(cps, moveNum)
     char message[MSG_SIZ];\r
     \r
     if (cps->useSetboard) {\r
-      char* fen = PositionToFEN(moveNum, cps->useFEN960);\r
+      char* fen = PositionToFEN(moveNum, cps->fenOverride);\r
       sprintf(message, "setboard %s\n", fen);\r
       SendToProgram(message, cps);\r
       free(fen);\r
@@ -5604,6 +5612,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                         machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);\r
                 GameEnds(machineWhite ? BlackWins : WhiteWins,\r
                            buf1, GE_XBOARD);\r
+               return;\r
            } else if(gameInfo.variant != VariantFischeRandom && gameInfo.variant != VariantCapaRandom)\r
            /* [HGM] Kludge to handle engines that send FRC-style castling\r
               when they shouldn't (like TSCP-Gothic) */\r
@@ -5637,9 +5646,9 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
          if(appData.autoKibitz && !appData.icsEngineAnalyze ) { /* [HGM] kibitz: send most-recent PV info to ICS */\r
                char buf[3*MSG_SIZ];\r
 \r
-               sprintf(buf, "kibitz %d/%+.2f (%.2f sec, %.0f nodes, %1.0f knps) PV = %s\n",\r
-                       programStats.depth,\r
+               sprintf(buf, "kibitz %+.2f/%d (%.2f sec, %.0f nodes, %1.0f knps) PV=%s\n",\r
                        programStats.score / 100.,\r
+                       programStats.depth,\r
                        programStats.time / 100.,\r
                        u64ToDouble(programStats.nodes),\r
                        u64ToDouble(programStats.nodes) / (10*abs(programStats.time) + 1.),\r
@@ -5697,41 +5706,6 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
             int k, count = 0, epFile = epStatus[forwardMostMove]; static int bare = 1;\r
          if(gameInfo.holdingsSize == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {\r
 \r
-            if(appData.testLegality)\r
-            // don't wait for engine to announce game end if we can judge ourselves\r
-            switch (MateTest(boards[forwardMostMove],\r
-                                 PosFlags(forwardMostMove), epFile,\r
-                                       castlingRights[forwardMostMove]) ) {\r
-             case MT_NONE:\r
-             case MT_CHECK:\r
-             default:\r
-               break;\r
-             case MT_STALEMATE:\r
-               epStatus[forwardMostMove] = EP_STALEMATE;\r
-                if(appData.checkMates) {\r
-                   SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
-                   ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
-                   if(gameInfo.variant == VariantLosers || gameInfo.variant == VariantSuicide\r
-                                                        || gameInfo.variant == VariantGiveaway) // [HGM] losers:\r
-                       GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, // stalemated side wins!\r
-                               "Xboard adjudication: Stalemate", GE_XBOARD );\r
-                   else\r
-                       GameEnds( GameIsDrawn, "Xboard adjudication: Stalemate", GE_XBOARD );\r
-                   return;\r
-               }\r
-               break;\r
-             case MT_CHECKMATE:\r
-               epStatus[forwardMostMove] = EP_CHECKMATE;\r
-                if(appData.checkMates) {\r
-                   SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
-                   ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
-                   GameEnds( WhiteOnMove(forwardMostMove) != (gameInfo.variant == VariantLosers) // [HGM] losers:\r
-                            ? BlackWins : WhiteWins,            // reverse the result ( A!=1 is !A for a boolean)\r
-                            "Xboard adjudication: Checkmate", GE_XBOARD );\r
-                   return;\r
-               }\r
-               break;\r
-           }\r
 \r
            if( appData.testLegality )\r
            {   /* [HGM] Some more adjudications for obstinate engines */\r
@@ -5740,7 +5714,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                     NrPieces=0, NrPawns=0, PawnAdvance=0, i, j;\r
                static int moveCount = 6;\r
 \r
-                /* First absolutely insufficient mating material. Count what is on board. */\r
+                /* Count what is on board. */\r
                for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++)\r
                {   ChessSquare p = boards[forwardMostMove][i][j];\r
                    int m=i;\r
@@ -5786,6 +5760,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                    }\r
                 }\r
 \r
+               /* Some material-based adjudications that have to be made before stalemate test */\r
                if(gameInfo.variant == VariantAtomic && NrK < 2) {\r
                    // [HGM] atomic: stm must have lost his King on previous move, as destroying own K is illegal\r
                     epStatus[forwardMostMove] = EP_CHECKMATE; // make claimable as if stm is checkmated\r
@@ -5825,6 +5800,43 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                 } else bare = 1;\r
 \r
 \r
+            // don't wait for engine to announce game end if we can judge ourselves\r
+            switch (MateTest(boards[forwardMostMove],\r
+                                 PosFlags(forwardMostMove), epFile,\r
+                                       castlingRights[forwardMostMove]) ) {\r
+             case MT_NONE:\r
+             case MT_CHECK:\r
+             default:\r
+               break;\r
+             case MT_STALEMATE:\r
+               if(epStatus[forwardMostMove] != EP_CHECKMATE) // [HGM] spare win through baring or K-capt\r
+                   epStatus[forwardMostMove] = EP_STALEMATE;\r
+                if(appData.checkMates) {\r
+                   SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
+                   ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+                   if(gameInfo.variant == VariantLosers || gameInfo.variant == VariantSuicide\r
+                                                        || gameInfo.variant == VariantGiveaway) // [HGM] losers:\r
+                       GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, // stalemated side wins!\r
+                               "Xboard adjudication: Stalemate", GE_XBOARD );\r
+                   else\r
+                       GameEnds( GameIsDrawn, "Xboard adjudication: Stalemate", GE_XBOARD );\r
+                   return;\r
+               }\r
+               break;\r
+             case MT_CHECKMATE:\r
+               epStatus[forwardMostMove] = EP_CHECKMATE;\r
+                if(appData.checkMates) {\r
+                   SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
+                   ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+                   GameEnds( WhiteOnMove(forwardMostMove) != (gameInfo.variant == VariantLosers) // [HGM] losers:\r
+                            ? BlackWins : WhiteWins,            // reverse the result ( A!=1 is !A for a boolean)\r
+                            "Xboard adjudication: Checkmate", GE_XBOARD );\r
+                   return;\r
+               }\r
+               break;\r
+           }\r
+\r
+                /* Next absolutely insufficient mating material. */\r
                 if( NrPieces == 2 || gameInfo.variant != VariantXiangqi && \r
                                     gameInfo.variant != VariantShatranj && // [HGM] baring will remain possible\r
                        (NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 ||\r
@@ -9484,7 +9496,7 @@ SaveGamePGN(f)
     PrintPGNTags(f, &gameInfo);\r
     \r
     if (backwardMostMove > 0 || startedFromSetupPosition) {\r
-        char *fen = PositionToFEN(backwardMostMove, 1);\r
+        char *fen = PositionToFEN(backwardMostMove, NULL);\r
         fprintf(f, "[FEN \"%s\"]\n[SetUp \"1\"]\n", fen);\r
        fprintf(f, "\n{--------------\n");\r
        PrintPosition(f, backwardMostMove);\r
@@ -9547,7 +9559,16 @@ SaveGamePGN(f)
        linelen += numlen;\r
 \r
        /* Get move */\r
-       movelen = strlen(parseList[i]); /* [HGM] pgn: line-break point before move */\r
+       strcpy(move_buffer, parseList[i]); // [HGM] pgn: print move via buffer, so it can be edited\r
+       movelen = strlen(move_buffer); /* [HGM] pgn: line-break point before move */\r
+        if( i >= 0 && appData.saveExtendedInfoInPGN && pvInfoList[i].depth > 0 ) {\r
+               int p = movelen - 1;\r
+               if(move_buffer[p] == ' ') p--;\r
+               if(move_buffer[p] == ')') { // [HGM] pgn: strip off ICS time if we have extended info\r
+                   while(p && move_buffer[--p] != '(');\r
+                   if(p && move_buffer[p-1] == ' ') move_buffer[movelen=p-1] = 0;\r
+               }\r
+        }\r
 \r
        /* Print move */\r
        blank = linelen > 0 && movelen > 0;\r
@@ -9560,7 +9581,7 @@ SaveGamePGN(f)
            fprintf(f, " ");\r
            linelen++;\r
        }\r
-       fprintf(f, parseList[i]);\r
+       fprintf(f, move_buffer);\r
        linelen += movelen;\r
 \r
         /* [AS] Add PV info if present */\r
@@ -9568,14 +9589,14 @@ SaveGamePGN(f)
             /* [HGM] add time */\r
             char buf[MSG_SIZ]; int seconds = 0;\r
 \r
-#if 0\r
+#if 1\r
             if(i >= backwardMostMove) {\r
                if(WhiteOnMove(i))\r
                        seconds = timeRemaining[0][i] - timeRemaining[0][i+1]\r
-                                 + GetTimeQuota(i/2) / WhitePlayer()->timeOdds;\r
+                                 + GetTimeQuota(i/2) / (1000*WhitePlayer()->timeOdds);\r
                else\r
                        seconds = timeRemaining[1][i] - timeRemaining[1][i+1]\r
-                                  + GetTimeQuota(i/2) / WhitePlayer()->other->timeOdds;\r
+                                  + GetTimeQuota(i/2) / (1000*WhitePlayer()->other->timeOdds);\r
             }\r
             seconds = (seconds+50)/100; // deci-seconds, rounded to nearest\r
 #else\r
@@ -9757,7 +9778,7 @@ SavePosition(f, dummy, dummy2)
        PrintPosition(f, currentMove);\r
        fprintf(f, "--------------]\n");\r
     } else {\r
-       fen = PositionToFEN(currentMove, 1);\r
+       fen = PositionToFEN(currentMove, NULL);\r
        fprintf(f, "%s\n", fen);\r
        free(fen);\r
     }\r
@@ -13293,9 +13314,9 @@ PGNDate()
 \r
 \r
 char *\r
-PositionToFEN(move, useFEN960)\r
+PositionToFEN(move, overrideCastling)\r
      int move;\r
-     int useFEN960;\r
+     char *overrideCastling;\r
 {\r
     int i, j, fromX, fromY, toX, toY;\r
     int whiteToPlay;\r
@@ -13370,6 +13391,9 @@ PositionToFEN(move, useFEN960)
     *p++ = whiteToPlay ? 'w' : 'b';\r
     *p++ = ' ';\r
 \r
+  if(q = overrideCastling) { // [HGM] FRC: override castling & e.p fields for non-compliant engines\r
+    while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' ';\r
+  } else {\r
   if(nrCastlingRights) {\r
      q = p;\r
      if(gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom) {\r
@@ -13427,6 +13451,7 @@ PositionToFEN(move, useFEN960)
     }\r
     *p++ = ' ';\r
   }\r
+  }\r
 \r
     /* [HGM] find reversible plies */\r
     {   int i = 0, j=move;\r